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