00001
00002
00003
00004
00005
00006
00007
00008 #ifndef MATRIX_NXN_H_INCLUDED
00009 #define MATRIX_NXN_H_INCLUDED
00010
00011 #define MATRIX_NXN_HEAP
00012
00013
00014 #ifdef _WIN32
00015 #pragma warning(disable:4786)
00016
00017 #endif
00018
00019 #include "MVTools.h"
00020 #include "Vector_n.h"
00021
00022
00023 #if !defined(MATRIX_NXN_STACK) && !defined(MATRIX_NXN_HEAP)
00024 #error Define MATRIX_NXN_STACK if you'd like Matrix_nxn to use stack memory or \
00025 MATRIX_NXN_HEAP if you'd like Matrix_nxn to use heap memory!
00026 #endif
00027
00028
00029
00030 template <class T, size_t N>
00031 class Matrix_nxn;
00032 template<class T, size_t N>
00033 Matrix_nxn<T, N> operator*(const Matrix_nxn<T, N>& m1,
00034 const Matrix_nxn<T, N>& m2);
00035
00036
00037
00038
00039
00040
00041
00042
00043 template <class T, size_t N>
00044 class Matrix_nxn
00045 {
00046 public:
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 Matrix_nxn()
00057 {
00058 #ifdef MATRIX_NXN_HEAP
00059 content = new Vector_n<T, N>[N];
00060 #endif
00061
00062 Vector_n<T, N>* init = content;
00063 Vector_n<T, N> zero = Vector_n<T, N>();
00064 for (size_t i = 0; i < N; ++i, ++init)
00065 *init = zero;
00066 }
00067
00068
00069
00070
00071
00072
00073
00074 Matrix_nxn(const T* v)
00075 {
00076 #ifdef MATRIX_NXN_HEAP
00077 content = new Vector_n<T, N>[N];
00078 #endif
00079
00080 Vector_n<T, N>* init = content;
00081 for (size_t i = 0; i < N; ++i, ++init, v+=N)
00082 *init = Vector_n<T, N>(v);
00083 }
00084
00085
00086
00087
00088
00089
00090
00091 Matrix_nxn(const Matrix_nxn<T, N>& m)
00092 {
00093 #ifdef MATRIX_NXN_HEAP
00094 content = new Vector_n<T, N>[N];
00095 #endif
00096
00097 *this = m;
00098 }
00099
00100
00101
00102
00103
00104
00105 ~Matrix_nxn()
00106 {
00107 #ifdef MATRIX_NXN_HEAP
00108 delete [] content;
00109 #endif
00110 }
00111
00112
00113
00114
00115
00116
00117
00118 Matrix_nxn<T, N>& operator=(const Matrix_nxn<T, N>& m)
00119 {
00120 for (size_t i = 0; i < N; ++i)
00121 content[i] = m.content[i];
00122 return *this;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131 Matrix_nxn<T, N>& operator=(const T* m)
00132 {
00133 for (size_t i = 0; i < N; ++i)
00134 for (size_t j = 0; j <N; ++j, ++m)
00135 content[i][j] = *m;
00136 return *this;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145 void copyTo(T* m) const
00146 {
00147 const Vector_n<T, N>* con = content;
00148 for (size_t i = 0; i < N; ++i, m+=N, ++con)
00149 con->copyTo(m);
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159 const Vector_n<T, N>& operator[](size_t i) const
00160 {
00161 return content[i];
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171 Vector_n<T, N>& operator[](size_t i)
00172 {
00173 return content[i];
00174 }
00175
00176
00177
00178
00179
00180
00181
00182 Matrix_nxn<T, N>& operator+=(const Matrix_nxn<T, N>& m)
00183 {
00184 for (size_t i = 0; i < N; ++i)
00185 content[i] += m.content[i];
00186 return *this;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 Matrix_nxn<T, N>& operator-=(const Matrix_nxn<T, N>& m)
00196 {
00197 for (size_t i = 0; i < N; ++i)
00198 content[i] -= m.content[i];
00199 return *this;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 Matrix_nxn<T, N>& operator*=(const Matrix_nxn<T, N>& m)
00209 {
00210 *this = *this * m;
00211 return *this;
00212 }
00213
00214
00215
00216
00217
00218
00219
00220 Matrix_nxn<T, N>& operator/=(const Matrix_nxn<T, N>& m)
00221 {
00222 *this = *this / m;
00223 return *this;
00224 }
00225
00226
00227
00228
00229 Matrix_nxn<T, N> transpose()
00230 {
00231
00232 Matrix_nxn<T, N> res;
00233 for (size_t i = 0; i < N; ++i)
00234 for (size_t j = 0; j < N; ++j)
00235 res[i][j] = (*this)[j][i];
00236 return res;
00237 }
00238
00239
00240
00241
00242
00243 Matrix_nxn<T, N> invert()
00244 {
00245 Matrix_nxn<T, N> left(*this);
00246 Matrix_nxn<T, N> right(Matrix_nxn::identity());
00247 Vector_n<int, N> ranking;
00248
00249 int i;
00250 for (i = 0; i < (int)N; ++i)
00251 {
00252 ranking[i] = i;
00253 }
00254
00255 T zero = T();
00256 int r, r2, maxrow;
00257 for (r = 0; r < (int)(N-1); ++r)
00258 {
00259
00260 T maxval = left[ranking[r]][r];
00261 maxrow = r;
00262 if (maxval < zero)
00263 maxval = -maxval;
00264 for (r2 = r+1; r2 < (int)N; ++r2)
00265 {
00266 T val = left[ranking[r2]][r];
00267 if (val < zero)
00268 val = -val;
00269 if (val > maxval)
00270 {
00271 maxval = val;
00272 maxrow = r2;
00273 }
00274 }
00275
00276
00277 int temp = ranking[r];
00278 ranking[r] = ranking[maxrow];
00279 ranking[maxrow] = temp;
00280
00281 if (MVTools::isNearZero(left[ranking[r]][r]))
00282 {
00283 if (MVTools::isNearNegZero(left[ranking[r]][r]))
00284 throw MVException(MVException::DivByNegZero);
00285 else
00286 throw MVException(MVException::DivByPosZero);
00287 }
00288
00289 for (r2 = r+1; r2 < (int)N; ++r2)
00290 {
00291
00292 T factor = left[ranking[r2]][r] / left[ranking[r]][r];
00293 if (MVTools::isNearInf(factor))
00294 {
00295 if (MVTools::isNearPosInf(factor))
00296 throw MVException(MVException::PosInfValue);
00297 else
00298 throw MVException(MVException::NegInfValue);
00299 }
00300
00301
00302 left[ranking[r2]] -= factor*left[ranking[r]];
00303
00304
00305 right[ranking[r2]] -= factor*right[ranking[r]];
00306 }
00307 }
00308
00309
00310
00311 for (r = (int)(N-1); r > 0; --r)
00312 {
00313 if (MVTools::isNearZero(left[ranking[r]][r]))
00314 {
00315 if (MVTools::isNearNegZero(left[ranking[r]][r]))
00316 throw MVException(MVException::DivByNegZero);
00317 else
00318 throw MVException(MVException::DivByPosZero);
00319 }
00320 for (r2 = r-1; r2 >= 0; --r2)
00321 {
00322 T factor = left[ranking[r2]][r] / left[ranking[r]][r];
00323 if (MVTools::isNearInf(factor))
00324 {
00325 if (MVTools::isNearPosInf(factor))
00326 throw MVException(MVException::PosInfValue);
00327 else
00328 throw MVException(MVException::NegInfValue);
00329 }
00330
00331
00332 left[ranking[r2]] -= factor*left[ranking[r]];
00333
00334
00335 right[ranking[r2]] -= factor*right[ranking[r]];
00336 }
00337 }
00338
00339
00340
00341 Matrix_nxn<T, N> res;
00342 for (r = 0; r < (int)N; ++r)
00343 {
00344 res[r] = right[ranking[r]];
00345
00346 if (MVTools::isNearZero(left[ranking[r]][r]))
00347 {
00348 if (MVTools::isNearNegZero(left[ranking[r]][r]))
00349 throw MVException(MVException::DivByNegZero);
00350 else
00351 throw MVException(MVException::DivByPosZero);
00352 }
00353 res[r] /= left[ranking[r]][r];
00354 }
00355
00356 return res;
00357 }
00358
00359
00360
00361
00362
00363 Matrix_nxn<T, N> invert2()
00364 {
00365 Matrix_nxn<T, N> res;
00366 for (size_t i = 0; i < N; ++i)
00367 {
00368 Vector_n<T, N> e;
00369 e[i] = (T)1;
00370 res[i] = *this.solve(e);
00371 }
00372 return res.transpose();
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 Vector_n<T, N> solve(Vector_n<T, N> b) const
00384 {
00385
00386 Matrix_nxn<T, N> m(*this);
00387
00388
00389 Vector_n<int, N> ranking;
00390 size_t i;
00391 for (i = 0; i < N; ++i)
00392 ranking[i] = i;
00393
00394 T z = T();
00395 int c;
00396 int r;
00397 for (c = 0; c < (int)N-1; ++c)
00398 {
00399
00400 int maxRow = c;
00401 T maxValue = m[ranking[maxRow]][c];
00402 if (maxValue < z)
00403 maxValue = -maxValue;
00404 for (r = c+1; r < (int)N; ++r)
00405 {
00406 T value = m[ranking[r]][c];
00407 if (value < z)
00408 value = -value;
00409 if (value > maxValue)
00410 {
00411 maxRow = r;
00412 maxValue = value;
00413 }
00414 }
00415
00416
00417 if (MVTools::isNearZero(maxValue))
00418 {
00419 if (MVTools::isNearNegZero(maxValue))
00420 throw MVException(MVException::DivByNegZero);
00421 else
00422 throw MVException(MVException::DivByPosZero);
00423 }
00424
00425
00426
00427
00428
00429
00430 int temp = ranking[c];
00431 ranking[c] = ranking[maxRow];
00432 ranking[maxRow] = temp;
00433
00434
00435 for (r = c+1; r < (int)N; ++r)
00436 {
00437
00438 T factor = m[ranking[r]][c] / m[ranking[c]][c];
00439 if (MVTools::isNearInf(factor))
00440 {
00441 if (MVTools::isNearPosInf(factor))
00442 throw MVException(MVException::PosInfValue);
00443 else
00444 throw MVException(MVException::NegInfValue);
00445 }
00446
00447 T sub;
00448 sub = factor*b[ranking[c]];
00449 if (MVTools::isNearInf(sub))
00450 {
00451 if (MVTools::isNearPosInf(sub))
00452 throw MVException(MVException::PosInfValue);
00453 else
00454 throw MVException(MVException::NegInfValue);
00455 }
00456
00457
00458 b[ranking[r]] -= sub;
00459
00460
00461 m[ranking[r]][c] = T();
00462 for (int c2 = c+1; c2 < (int)N; ++c2)
00463 {
00464 sub = factor*m[ranking[c]][c2];
00465 if (MVTools::isNearInf(sub))
00466 {
00467 if (MVTools::isNearPosInf(sub))
00468 throw MVException(MVException::PosInfValue);
00469 else
00470 throw MVException(MVException::NegInfValue);
00471 }
00472 m[ranking[r]][c2] -= sub;
00473 }
00474 }
00475 }
00476
00477
00478 if (MVTools::isNearZero(m[ranking[N-1]][N-1]))
00479 {
00480 if (MVTools::isNearNegZero(m[ranking[N-1]][N-1]))
00481 throw MVException(MVException::DivByNegZero);
00482 else
00483 throw MVException(MVException::DivByPosZero);
00484 }
00485
00486
00487
00488
00489
00490
00491
00492 b[ranking[N-1]] /= m[ranking[N-1]][N-1];
00493 for (r = N-2; r >= 0; --r)
00494 {
00495 T sum = T();
00496 for (c = r+1; c < (int)N; ++c)
00497 sum += m[ranking[r]][c] * b[ranking[c]];
00498 if (MVTools::isNearInf(sum))
00499 {
00500 if (MVTools::isNearPosInf(sum))
00501 throw MVException(MVException::PosInfValue);
00502 else
00503 throw MVException(MVException::NegInfValue);
00504 }
00505
00506 if (MVTools::isNearZero(m[ranking[r]][r]))
00507 {
00508 if (MVTools::isNearNegZero(m[ranking[r]][r]))
00509 throw MVException(MVException::DivByNegZero);
00510 else
00511 throw MVException(MVException::DivByPosZero);
00512 }
00513 b[ranking[r]] = (b[ranking[r]] - sum) / m[ranking[r]][r];
00514
00515 if (MVTools::isNearInf(b[ranking[r]]))
00516 {
00517 if (MVTools::isNearPosInf(b[ranking[r]]))
00518 throw MVException(MVException::PosInfValue);
00519 else
00520 throw MVException(MVException::NegInfValue);
00521 }
00522 }
00523
00524
00525 Vector_n<T, N> x;
00526 for (r = 0; r < (int)N; ++r)
00527 x[r] = b[ranking[r]];
00528
00529 return x;
00530 }
00531
00532
00533
00534
00535
00536
00537
00538 T det() const
00539 {
00540
00541 Matrix_nxn<T, N> m(*this);
00542
00543
00544 Vector_n<int, N> ranking;
00545 size_t i;
00546 for (i = 0; i < N; ++i)
00547 ranking[i] = i;
00548
00549 T z = T();
00550 bool bPositive = true;
00551 int c;
00552 int r;
00553 for (c = 0; c < (int)(N-1); ++c)
00554 {
00555
00556 int maxRow = c;
00557 T maxValue = m[ranking[maxRow]][c];
00558 if (maxValue < z)
00559 maxValue = -maxValue;
00560 for (r = c+1; r < (int)N; ++r)
00561 {
00562 T value = m[ranking[r]][c];
00563 if (value < z)
00564 value = -value;
00565 if (value > maxValue)
00566 {
00567 maxRow = r;
00568 maxValue = value;
00569 }
00570 }
00571
00572
00573 if (MVTools::isNearZero(maxValue))
00574 return z;
00575
00576
00577
00578
00579 if (c != maxRow)
00580 {
00581 int temp = ranking[c];
00582 ranking[c] = ranking[maxRow];
00583 ranking[maxRow] = temp;
00584 bPositive = !bPositive;
00585 }
00586
00587
00588 for (r = c+1; r < (int)N; ++r)
00589 {
00590
00591 T factor = m[ranking[r]][c] / m[ranking[c]][c];
00592 if (MVTools::isNearInf(factor))
00593 {
00594 if (MVTools::isNearPosInf(factor))
00595 throw MVException(MVException::PosInfValue);
00596 else
00597 throw MVException(MVException::NegInfValue);
00598 }
00599
00600
00601 m[ranking[r]][c] = T();
00602 for (int c2 = c+1; c2 < (int)N; ++c2)
00603 {
00604 m[ranking[r]][c2] -= factor*m[ranking[c]][c2];
00605 T sub;
00606 sub = factor*m[ranking[c]][c2];
00607 if (MVTools::isNearInf(sub))
00608 {
00609 if (MVTools::isNearPosInf(sub))
00610 throw MVException(MVException::PosInfValue);
00611 else
00612 throw MVException(MVException::NegInfValue);
00613 }
00614 }
00615 }
00616 }
00617
00618
00619 if (MVTools::isNearZero(m[ranking[N-1]][N-1]))
00620 return z;
00621
00622
00623
00624
00625
00626 T res = m[ranking[0]][0];
00627 for (r = 1; r < (int)N; ++r)
00628 {
00629 res *= m[ranking[r]][r];
00630 if (MVTools::isNearInf(res))
00631 {
00632 if (MVTools::isNearPosInf(res))
00633 throw MVException(MVException::PosInfValue);
00634 else
00635 throw MVException(MVException::NegInfValue);
00636 }
00637 }
00638
00639 if (!bPositive)
00640 res = -res;
00641 return res;
00642 }
00643
00644
00645
00646
00647
00648 static Matrix_nxn<T, N> identity()
00649 {
00650 Matrix_nxn<T, N> res;
00651 for (size_t i = 0; i < N; ++i)
00652 res[i][i] = (T)1;
00653 return res;
00654 }
00655
00656 private:
00657
00658 #if defined(MATRIX_NXN_HEAP)
00659 Vector_n<T, N>* content;
00660 #elif defined(MATRIX_NXN_STACK)
00661 Vector_n<T, N> content[N];
00662 #endif
00663 };
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 template<class T, size_t N>
00674 Matrix_nxn<T, N> operator+(const Matrix_nxn<T, N>& m1,
00675 const Matrix_nxn<T, N>& m2)
00676 {
00677 Matrix_nxn<T, N> res(m1);
00678 res += m2;
00679 return res;
00680 }
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 template<class T, size_t N>
00691 Matrix_nxn<T, N> operator-(const Matrix_nxn<T, N>& m1,
00692 const Matrix_nxn<T, N>& m2)
00693 {
00694 Matrix_nxn<T, N> res(m1);
00695 res -= m2;
00696 return res;
00697 }
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 template<class T, size_t N>
00708 Matrix_nxn<T, N> operator*(const Matrix_nxn<T, N>& m1,
00709 const Matrix_nxn<T, N>& m2)
00710 {
00711 Matrix_nxn<T, N> res;
00712 size_t i, j, k;
00713 for (i = 0; i < N; ++i)
00714 {
00715 for (j = 0; j < N; ++j)
00716 {
00717 for (k = 0; k < N; ++k)
00718 {
00719 res[i][j] += m1[i][k] * m2[k][j];
00720 }
00721 if (MVTools::isNearInf(res[i][j]))
00722 {
00723 if (MVTools::isNearPosInf(res[i][j]))
00724 throw MVException(MVException::PosInfValue);
00725 else
00726 throw MVException(MVException::NegInfValue);
00727 }
00728 }
00729 }
00730 return res;
00731 }
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741 template<class T, size_t N>
00742 Vector_n<T, N> operator*(const Matrix_nxn<T, N>& m,
00743 const Vector_n<T, N>& v)
00744 {
00745 Vector_n<T, N> res;
00746 for (size_t i = 0; i < N; ++i)
00747 {
00748 for (size_t j = 0; j < N; ++j)
00749 {
00750 res[i] += m[i][j]*v[j];
00751 }
00752 if (MVTools::isNearInf(res[i]))
00753 {
00754 if (MVTools::isNearPosInf(res[i]))
00755 throw MVException(MVException::PosInfValue);
00756 else
00757 throw MVException(MVException::NegInfValue);
00758 }
00759 }
00760 return res;
00761 }
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772 template<class T, size_t N>
00773 Matrix_nxn<T, N> operator/(const Matrix_nxn<T, N>& m1,
00774 const Matrix_nxn<T, N>& m2)
00775 {
00776 return m1*m2.invert();
00777 }
00778
00779 #endif
00780