00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <cassert>
00015 #include "intutils.h"
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 namespace atlas {
00026
00027 namespace matrix {
00028
00029 namespace {
00030
00031 template<typename C> void blockReduce(Matrix<C>&, size_t, Matrix<C>&,
00032 Matrix<C>&);
00033 template<typename C> void blockShape(Matrix<C>&, size_t, Matrix<C>&,
00034 Matrix<C>&);
00035 template<typename C> void columnReduce(Matrix<C>&, size_t, size_t, Matrix<C>&);
00036 template<typename C> bool hasBlockReduction(const Matrix<C>&, size_t);
00037 template<typename C> bool hasReduction(const Matrix<C>&, size_t);
00038 template<typename C> typename Matrix<C>::index_pair
00039 findBlockReduction(const Matrix<C>&, size_t);
00040 template<typename C> typename Matrix<C>::index_pair
00041 findReduction(const Matrix<C>&, size_t);
00042 template<typename C> void rowReduce(Matrix<C>&, size_t, size_t, Matrix<C>&);
00043
00044 }
00045
00046 }
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 namespace matrix {
00058
00059
00060
00061 template<typename C>
00062 Matrix<C>::Matrix(const std::vector<std::vector<C> >& b)
00063
00064
00065
00066
00067
00068
00069 {
00070 if (b.empty()) {
00071 d_rows = 0;
00072 d_columns = 0;
00073 return;
00074 }
00075
00076 d_rows = b[0].size();
00077 d_columns = b.size();
00078 d_data.resize(d_rows*d_columns);
00079
00080 for (size_t j = 0; j < d_columns; ++j) {
00081 for (size_t i = 0; i < d_rows; ++i)
00082 (*this)(i,j) = b[j][i];
00083 }
00084 }
00085
00086 template<typename C>
00087 Matrix<C>::Matrix(const Matrix<C>& m, const std::vector<std::vector<C> >& b)
00088 :d_data(m.d_data), d_rows(m.d_rows), d_columns(m.d_columns)
00089
00090
00091
00092
00093
00094
00095
00096 {
00097 Matrix<C> p(b);
00098 invConjugate(*this,p);
00099 }
00100
00101 template<typename C>
00102 Matrix<C>::Matrix(const Matrix<C>& source, size_t r_first, size_t c_first,
00103 size_t r_last, size_t c_last)
00104 :d_data((r_last-r_first)*(c_last-c_first)),
00105 d_rows(r_last-r_first),
00106 d_columns(c_last-c_first)
00107
00108
00109
00110
00111
00112
00113 {
00114 for (size_t j = 0; j < d_columns; ++j)
00115 for (size_t i = 0; i < d_rows; ++i)
00116 (*this)(i,j) = source(r_first+i,c_first+j);
00117 }
00118
00119 template<typename C> template<typename I>
00120 Matrix<C>::Matrix(const Matrix<C>& m, const I& first, const I& last)
00121 :d_data(m.d_data), d_rows(m.d_rows), d_columns(m.d_columns)
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 {
00132 Matrix<C> p(first,last,tags::IteratorTag());
00133 invConjugate(*this,p);
00134 }
00135
00136 template<typename C>
00137 template<typename I> Matrix<C>::Matrix(const I& first, const I& last,
00138 tags::IteratorTag)
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 {
00152 std::vector<std::vector<C> > b(first,last);
00153
00154 if (b.empty()) {
00155 d_rows = 0;
00156 d_columns = 0;
00157 return;
00158 }
00159
00160 d_rows = b[0].size();
00161 d_columns = b.size();
00162 d_data.resize(d_rows*d_columns);
00163
00164 for (size_t i = 0; i < d_rows; ++i)
00165 for (size_t j = 0; j < d_columns; ++j)
00166 (*this)(i,j) = b[j][i];
00167 }
00168
00169
00170
00171 template<typename C>
00172 bool Matrix<C>::operator== (const Matrix<C>& m) const
00173
00174 {
00175 if ((d_rows != m.d_rows) or (d_columns != m.d_columns))
00176 return false;
00177
00178 return d_data == m.d_data;
00179 }
00180
00181 template<typename C>
00182 typename Matrix<C>::index_pair Matrix<C>::absMinPos(size_t i_min,
00183 size_t j_min) const
00184
00185
00186
00187
00188
00189
00190
00191 {
00192 C minCoeff = std::numeric_limits<C>::max();
00193 size_t i_m = d_rows;
00194 size_t j_m = d_columns;
00195
00196 for (size_t i = i_min; i < d_rows; ++i)
00197 for (size_t j = j_min; j < d_columns; ++j) {
00198 C c = (*this)(i,j);
00199 if (c == 0)
00200 continue;
00201 if (intutils::abs(c) < minCoeff) {
00202 minCoeff = intutils::abs(c);
00203 i_m = i;
00204 j_m = j;
00205 if (minCoeff == 1)
00206 break;
00207 }
00208 }
00209
00210 return std::make_pair(i_m,j_m);
00211 }
00212
00213 template<typename C>
00214 void Matrix<C>::apply(std::vector<C>& v, const std::vector<C>& w) const
00215
00216
00217
00218
00219
00220
00221
00222 {
00223 std::vector<C> tmp = w;
00224
00225 for (size_t i = 0; i < d_rows; ++i) {
00226 C c = 0;
00227 for (size_t j = 0; j < d_columns; ++j) {
00228 C m_ij = (*this)(i,j);
00229 c += m_ij*tmp[j];
00230 }
00231 v[i] = c;
00232 }
00233
00234 return;
00235 }
00236
00237 template<typename C> template<typename I, typename O>
00238 void Matrix<C>::apply(const I& first, const I& last, O out) const
00239
00240
00241
00242
00243
00244
00245
00246
00247 {
00248 for (I i = first; i != last; ++i) {
00249 std::vector<C> v(d_rows);
00250 apply(v,*i);
00251 *out++ = v;
00252 }
00253
00254 return;
00255 }
00256
00257 template<typename C>
00258 void Matrix<C>::column(std::vector<C>& v, size_t j) const
00259
00260
00261
00262
00263
00264 {
00265 v.resize(d_rows);
00266
00267 for (size_t i = 0; i < d_rows; ++i)
00268 v[i] = (*this)(i,j);
00269
00270 return;
00271 }
00272
00273 template<typename C>
00274 bool Matrix<C>::divisible(C c) const
00275
00276
00277
00278
00279
00280 {
00281 for (size_t j = 0; j < d_data.size(); ++j)
00282 if (d_data[j]%c)
00283 return false;
00284
00285 return true;
00286 }
00287
00288 template<typename C>
00289 void Matrix<C>::row(std::vector<C>& v, size_t i) const
00290
00291
00292
00293
00294
00295 {
00296 v.resize(d_columns);
00297
00298 for (size_t j = 0; j < d_columns; ++j)
00299 v[j] = (*this)(i,j);
00300
00301 return;
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311 template<typename C>
00312 Matrix<C>& Matrix<C>::operator+= (const Matrix<C>& m)
00313
00314 {
00315 for (size_t k = 0; k < d_data.size(); ++k) {
00316 d_data[k] += m.d_data[k];
00317 }
00318 }
00319
00320
00321
00322
00323
00324 template<typename C>
00325 Matrix<C>& Matrix<C>::operator-= (const Matrix<C>& m)
00326
00327
00328 {
00329 for (size_t k = 0; k < d_data.size(); ++k) {
00330 d_data[k] -= m.d_data[k];
00331 }
00332 }
00333
00334
00335 template<typename C>
00336 Matrix<C> Matrix<C>::operator* (const Matrix<C>& m) const
00337 {
00338 Matrix<C> result(d_rows,m.d_columns);
00339
00340 for (size_t i = 0; i < d_rows; ++i)
00341 for (size_t k = 0; k < m.d_columns; ++k)
00342 {
00343 C c=0;
00344 for (size_t j = 0; j < d_columns; ++j)
00345 c += (*this)(i,j) * m(j,k);
00346
00347 result(i,k)=c;
00348 }
00349
00350 return result;
00351 }
00352
00353
00354
00355
00356
00357
00358
00359 template<typename C>
00360 Matrix<C>& Matrix<C>::operator*= (const Matrix<C>& m)
00361
00362 {
00363
00364
00365 C zero = 0;
00366 Matrix<C> prod(d_rows,m.d_columns,zero);
00367
00368 for (size_t i = 0; i < d_rows; ++i)
00369 for (size_t j = 0; j < m.d_columns; ++j) {
00370 for (size_t k = 0; k < d_columns; ++k) {
00371 C t_ik = (*this)(i,k);
00372 C m_kj = m(k,j);
00373 prod(i,j) += t_ik * m_kj;
00374 }
00375 }
00376
00377 swap(prod);
00378
00379 return *this;
00380 }
00381
00382
00383 template<typename C>
00384 Matrix<C>& Matrix<C>::operator/= (const C& c)
00385
00386
00387
00388
00389
00390 {
00391 if (c == 1)
00392 return *this;
00393
00394 iterator e = end();
00395
00396 for (iterator i = begin(); i != e; ++i)
00397 *i /= c;
00398
00399 return *this;
00400 }
00401
00402 template<typename C>
00403 void Matrix<C>::changeColumnSign(size_t j)
00404
00405
00406
00407
00408
00409 {
00410 for (size_t i = 0; i < d_rows; ++i) {
00411 (*this)(i,j) *= -1;
00412 }
00413
00414 return;
00415 }
00416
00417 template<typename C>
00418 void Matrix<C>::changeRowSign(size_t i)
00419
00420
00421
00422
00423
00424 {
00425 for (size_t j = 0; j < d_columns; ++j) {
00426 (*this)(i,j) *= -1;
00427 }
00428
00429 return;
00430 }
00431
00432 template<typename C>
00433 void Matrix<C>::columnOperation(size_t i, size_t j, const C& c)
00434
00435
00436
00437
00438
00439
00440 {
00441 for (size_t k = 0; k < columnSize(); ++k)
00442 (*this)(k,i) += c*(*this)(k,j);
00443
00444 return;
00445 }
00446
00447 template<typename C>
00448 void Matrix<C>::copy(const Matrix<C>& source, size_t r, size_t c)
00449
00450
00451
00452
00453
00454
00455 {
00456 for (size_t j = 0; j < source.d_columns; ++j)
00457 for (size_t i = 0; i < source.d_rows; ++i)
00458 (*this)(r+i,c+j) = source(i,j);
00459
00460 return;
00461 }
00462
00463 template<typename C>
00464 void Matrix<C>::copyColumn(const Matrix<C>& m, size_t c_d, size_t c_s)
00465
00466
00467
00468
00469
00470
00471 {
00472 for (size_t i = 0; i < d_rows; ++i)
00473 (*this)(i,c_d) = m(i,c_s);
00474
00475 return;
00476 }
00477
00478 template<typename C>
00479 void Matrix<C>::copyRow(const Matrix<C>& m, size_t r_d, size_t r_s)
00480
00481
00482
00483
00484
00485
00486 {
00487 for (size_t j = 0; j < d_columns; ++j)
00488 (*this)(r_d,j) = m(r_s,j);
00489
00490 return;
00491 }
00492
00493 template<typename C>
00494 void Matrix<C>::eraseColumn(size_t j)
00495
00496
00497
00498
00499
00500 {
00501 iterator pos = begin() + j;
00502 --d_columns;
00503
00504 for (size_t k = 0; k < d_rows; ++k, pos += d_columns)
00505 d_data.erase(pos);
00506
00507 return;
00508 }
00509
00510 template<typename C>
00511 void Matrix<C>::eraseRow(size_t i)
00512
00513
00514
00515
00516
00517 {
00518 iterator first = begin() + i*d_columns;
00519 d_data.erase(first,first+d_columns);
00520 --d_rows;
00521
00522 return;
00523 }
00524
00525
00526
00527
00528
00529 template<typename C> void Matrix<C>::invert()
00530
00531 {
00532 C d; invert(d);
00533 assert(d==1);
00534 }
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 template<typename C>
00556 void Matrix<C>::invert(C& d)
00557 {
00558 assert(d_rows==d_columns);
00559 if (d_rows == 0)
00560 { d=1; return; }
00561
00562 C zero = 0;
00563 Matrix<C> row(d_rows,d_rows,zero);
00564
00565
00566
00567 for (size_t j = 0; j < d_rows; ++j)
00568 row(j,j) = 1;
00569
00570 Matrix<C> col(row);
00571
00572
00573
00574 for (size_t r = 0; r < d_rows; ++r) {
00575
00576 if (isZero(r,r)) {
00577 d = 0;
00578 return;
00579 }
00580
00581 index_pair k = absMinPos(r,r);
00582
00583 if (k.first > r) {
00584 swapRows(r,k.first);
00585 row.swapRows(r,k.first);
00586 }
00587
00588 if(k.second > r) {
00589 swapColumns(r,k.second);
00590 col.swapColumns(r,k.second);
00591 }
00592
00593 if ((*this)(r,r) < 0) {
00594 changeRowSign(r);
00595 row.changeRowSign(r);
00596 }
00597
00598
00599
00600 while (hasReduction(*this,r)) {
00601 k = findReduction(*this,r);
00602 if (k.first > r) {
00603 rowReduce(*this,k.first,r,row);
00604 }
00605 else {
00606 columnReduce(*this,k.second,r,col);
00607 }
00608 }
00609
00610
00611
00612 blockShape(*this,r,row,col);
00613 blockReduce(*this,r,row,col);
00614
00615 }
00616
00617
00618
00619 for (size_t j = 1; j < d_rows; ++j) {
00620 (*this)(j,j) *= (*this)(j-1,j-1);
00621 }
00622
00623
00624
00625 d = (*this)(d_rows-1,d_rows-1);
00626
00627 for (size_t j = 0; j < d_rows; ++j) {
00628 (*this)(j,j) = d/(*this)(j,j);
00629 }
00630
00631 col *= *this;
00632 col *= row;
00633 swap(col);
00634
00635 return;
00636 }
00637
00638 template<typename C>
00639 bool Matrix<C>::isZero(size_t i_min, size_t j_min) const
00640
00641
00642
00643
00644
00645 {
00646 if (d_data.size() == 0)
00647 return true;
00648
00649 for (size_t i = i_min; i < d_rows; ++i)
00650 for (size_t j = j_min; j < d_columns; ++j)
00651 if ((*this)(i,j))
00652 return false;
00653
00654 return true;
00655 }
00656
00657 template<typename C>
00658 void Matrix<C>::negate()
00659
00660
00661
00662
00663
00664 {
00665 for (size_t i = 0; i < d_rows; ++i)
00666 for (size_t j = 0; j < d_rows; ++j)
00667 (*this)(i,j) = -(*this)(i,j);
00668
00669 return;
00670 }
00671
00672 template<typename C>
00673 void Matrix<C>::permute(const setutils::Permutation& a)
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689 {
00690 Matrix<C> q(d_columns);
00691
00692 for (size_t j = 0; j < d_columns; ++j)
00693 for (size_t i = 0; i < d_rows; ++i) {
00694 size_t a_i = a[i];
00695 size_t a_j = a[j];
00696 q(i,j) = (*this)(a_i,a_j);
00697 }
00698
00699 swap(q);
00700
00701 return;
00702 }
00703
00704 template<typename C>
00705 void Matrix<C>::resize(size_t m, size_t n)
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 {
00716 d_data.resize(m*n);
00717 d_rows = m;
00718 d_columns = n;
00719
00720 return;
00721 }
00722
00723 template<typename C>
00724 void Matrix<C>::resize(size_t m, size_t n, const C& c)
00725
00726
00727
00728
00729
00730
00731
00732
00733 {
00734 d_data.assign(m*n,c);
00735 d_rows = m;
00736 d_columns = n;
00737
00738 return;
00739 }
00740
00741 template<typename C>
00742 void Matrix<C>::rowOperation(size_t i, size_t j, const C& c)
00743
00744
00745
00746
00747
00748
00749 {
00750 for (size_t k = 0; k < rowSize(); ++k)
00751 (*this)(i,k) += c*(*this)(j,k);
00752
00753 return;
00754 }
00755
00756 template<typename C>
00757 void Matrix<C>::swap(Matrix<C>& m)
00758
00759
00760
00761
00762
00763 {
00764
00765
00766 d_data.swap(m.d_data);
00767
00768
00769
00770 std::swap(d_rows,m.d_rows);
00771 std::swap(d_columns,m.d_columns);
00772
00773 return;
00774 }
00775
00776 template<typename C>
00777 void Matrix<C>::swapColumns(size_t i, size_t j)
00778
00779
00780
00781
00782
00783 {
00784 for (size_t k = 0; k < columnSize(); ++k) {
00785 C tmp = (*this)(k,i);
00786 (*this)(k,i) = (*this)(k,j);
00787 (*this)(k,j) = tmp;
00788 }
00789
00790 return;
00791 }
00792
00793 template<typename C>
00794 void Matrix<C>::swapRows(size_t i, size_t j)
00795
00796
00797
00798
00799
00800 {
00801 for (size_t k = 0; k < rowSize(); ++k) {
00802 C tmp = (*this)(i,k);
00803 (*this)(i,k) = (*this)(j,k);
00804 (*this)(j,k) = tmp;
00805 }
00806
00807 return;
00808 }
00809
00810 template<typename C> void Matrix<C>::transpose()
00811
00812
00813
00814
00815
00816
00817
00818 {
00819 if (d_rows == d_columns) {
00820 for (size_t j = 0; j < d_columns; ++j)
00821 for (size_t i = j+1; i < d_rows; ++i) {
00822 C t = (*this)(i,j);
00823 (*this)(i,j) = (*this)(j,i);
00824 (*this)(j,i) = t;
00825 }
00826 return;
00827 }
00828
00829
00830
00831 C zero = 0;
00832 std::vector<C> v(d_data.size(),zero);
00833 size_t k = 0;
00834
00835
00836
00837 for (size_t j = 0; j < d_columns; ++j)
00838 for (size_t i = 0; i < d_rows; ++i) {
00839 v[k] = (*this)(i,j);
00840 k++;
00841 }
00842
00843
00844
00845 d_data.swap(v);
00846
00847 size_t t = d_rows;
00848 d_rows = d_columns;
00849 d_columns = t;
00850
00851 return;
00852 }
00853
00854 }
00855
00856
00857
00858
00859
00860
00861
00862 namespace matrix {
00863
00864 template<typename C>
00865 void columnVectors(std::vector<std::vector<C> >& b, const Matrix<C>& m)
00866
00867
00868
00869
00870
00871 {
00872 b.resize(m.numColumns());
00873
00874 for (size_t j = 0; j < b.size(); ++j) {
00875 m.column(b[j],j);
00876 }
00877
00878 return;
00879 }
00880
00881 template<typename C>
00882 Matrix<C>& conjugate(Matrix<C>& m, const Matrix<C>& p)
00883
00884
00885
00886
00887
00888
00889
00890 {
00891 C d;
00892 Matrix<C> tmp(p*m*p.inverse(d));
00893 tmp /= d;
00894 m.swap(tmp);
00895
00896 return m;
00897 }
00898
00899 template<typename C>
00900 void extractBlock(Matrix<C>& dest, const Matrix<C>& source, size_t firstRow,
00901 size_t lastRow, size_t firstColumn, size_t lastColumn)
00902
00903
00904
00905
00906
00907
00908 {
00909 dest.resize(lastRow - firstRow, lastColumn - firstColumn);
00910
00911 for (size_t j = 0; j < dest.numColumns(); ++j)
00912 for (size_t i = 0; i < dest.numRows(); ++i)
00913 dest(i,j) = source(firstRow+i,firstColumn+j);
00914
00915 return;
00916 }
00917
00918 template<typename C>
00919 void extractMatrix(Matrix<C>& dest, const Matrix<C>& source,
00920 const std::vector<size_t>& r, const std::vector<size_t>& c)
00921
00922
00923
00924
00925
00926
00927 {
00928 dest.resize(r.size(),c.size());
00929
00930 for (size_t j = 0; j < c.size(); ++j)
00931 for (size_t i = 0; i < c.size(); ++i)
00932 dest(i,j) = source(r[i],c[j]);
00933
00934 return;
00935 }
00936
00937 template<typename C> void identityMatrix(Matrix<C>& m, size_t n)
00938
00939
00940
00941
00942
00943 {
00944 C zero = 0;
00945 m.resize(n,n,zero);
00946
00947 for (size_t j = 0; j < n; ++j)
00948 m(j,j) = 1;
00949
00950 return;
00951 }
00952
00953 template<typename C> void initBasis(std::vector<std::vector<C> >& b, size_t r)
00954
00955
00956
00957
00958
00959 {
00960 C zero = 0;
00961 b.assign(r,std::vector<C>(r,zero));
00962
00963 for (size_t j = 0; j < r; ++j) {
00964 b[j][j] = 1;
00965 }
00966
00967 return;
00968 }
00969
00970 template<typename C> Matrix<C>& invConjugate(Matrix<C>& m, const Matrix<C>& p)
00971
00972
00973
00974
00975
00976
00977
00978 {
00979 C d;
00980 Matrix<C> tmp(p.inverse(d)*m*p);
00981 tmp /= d;
00982 m.swap(tmp);
00983
00984 return m;
00985 }
00986
00987
00988
00989 }
00990
00991
00992
00993
00994
00995
00996
00997 namespace matrix {
00998
00999 namespace {
01000
01001 template<typename C>
01002 void blockReduce(Matrix<C>& m, size_t d, Matrix<C>& r, Matrix<C>& c)
01003
01004
01005
01006
01007
01008 {
01009 if (m(d,d) == 1)
01010 return;
01011
01012 while(hasBlockReduction(m,d)) {
01013 typename Matrix<C>::index_pair k = findBlockReduction(m,d);
01014 C one = 1;
01015 m.rowOperation(d,k.first,one);
01016 r.rowOperation(d,k.first,one);
01017 while (hasReduction(m,d)) {
01018 k = findReduction(m,d);
01019 if (k.first > d) {
01020 rowReduce(m,k.first,d,r);
01021 }
01022 else {
01023 columnReduce(m,k.second,d,c);
01024 }
01025 }
01026 blockShape(m,d,r,c);
01027 }
01028
01029 if (m(d,d) > 1)
01030 for (size_t j = d+1; j < m.rowSize(); ++j)
01031 for (size_t i = d+1; i < m.columnSize(); ++i)
01032 m(i,j) /= m(d,d);
01033
01034 return;
01035 }
01036
01037 template<typename C>
01038 void blockShape(Matrix<C>& m, size_t d, Matrix<C>& r,
01039 Matrix<C>& c)
01040
01041
01042
01043
01044
01045
01046 {
01047 C a = m(d,d);
01048
01049 for (size_t j = d+1; j < m.rowSize(); ++j) {
01050 if (m(d,j) == 0)
01051 continue;
01052 C q = m(d,j)/a;
01053 q = -q;
01054 m.columnOperation(j,d,q);
01055 c.columnOperation(j,d,q);
01056 }
01057
01058 for (size_t i = d+1; i < m.columnSize(); ++i) {
01059 if (m(i,d) == 0)
01060 continue;
01061 C q = m(i,d)/a;
01062 q = -q;
01063 m.rowOperation(i,d,q);
01064 r.rowOperation(i,d,q);
01065 }
01066
01067 return;
01068 }
01069
01070 template<typename C>
01071 void columnReduce(Matrix<C>& m, size_t j,
01072 size_t d, Matrix<C>& c)
01073
01074
01075
01076
01077
01078
01079
01080
01081 {
01082 C a = m(d,d);
01083 C q = intutils::divide(m(d,j),a);
01084 q = -q;
01085 m.columnOperation(j,d,q);
01086 c.columnOperation(j,d,q);
01087 m.swapColumns(d,j);
01088 c.swapColumns(d,j);
01089
01090 return;
01091 }
01092
01093 template<typename C>
01094 typename Matrix<C>::index_pair findBlockReduction(const Matrix<C>& m,
01095 size_t r)
01096
01097
01098
01099
01100
01101
01102 {
01103 C a = m(r,r);
01104
01105 for (size_t j = r+1; j < m.rowSize(); ++j) {
01106 for (size_t i = r+1; i < m.columnSize(); ++i) {
01107 if (m(i,j)%a)
01108 return std::make_pair(i,j);
01109 }
01110 }
01111
01112
01113 return std::make_pair(static_cast<size_t>(0ul),static_cast<size_t>(0ul));
01114 }
01115
01116 template<typename C>
01117 typename Matrix<C>::index_pair findReduction(const Matrix<C>& m,
01118 size_t r)
01119
01120
01121
01122
01123
01124
01125 {
01126 C a = m(r,r);
01127
01128 for (size_t j = r+1; j < m.rowSize(); ++j) {
01129 if (m(r,j)%a)
01130 return std::make_pair(r,j);
01131 }
01132
01133 for (size_t i = r+1; i < m.columnSize(); ++i) {
01134 if (m(i,r)%a)
01135 return std::make_pair(i,r);
01136 }
01137
01138
01139 return std::make_pair(static_cast<size_t>(0ul),static_cast<size_t>(0ul));
01140 }
01141
01142 template<typename C>
01143 bool hasBlockReduction(const Matrix<C>& m, size_t r)
01144
01145
01146
01147
01148
01149
01150 {
01151 C a = m(r,r);
01152
01153 if (a == 1)
01154 return false;
01155
01156 for (size_t j = r+1; j < m.rowSize(); ++j) {
01157 for (size_t i = r+1; i < m.columnSize(); ++i) {
01158 if (m(i,j)%a)
01159 return true;
01160 }
01161 }
01162
01163 return false;
01164 }
01165
01166 template<typename C>
01167 bool hasReduction(const Matrix<C>& m, size_t r)
01168
01169
01170
01171
01172
01173
01174 {
01175 C a = m(r,r);
01176
01177 if (a == 1)
01178 return false;
01179
01180 for (size_t j = r+1; j < m.rowSize(); ++j) {
01181 if (m(r,j)%a)
01182 return true;
01183 }
01184
01185 for (size_t i = r+1; i < m.columnSize(); ++i) {
01186 if (m(i,r)%a)
01187 return true;
01188 }
01189
01190 return false;
01191 }
01192
01193 template<typename C>
01194 void rowReduce(Matrix<C>& m, size_t i, size_t d, Matrix<C>& r)
01195
01196
01197
01198
01199
01200
01201
01202
01203 {
01204 C a = m(d,d);
01205 C q = intutils::divide(m(i,d),a);
01206 q = -q;
01207 m.rowOperation(i,d,q);
01208 r.rowOperation(i,d,q);
01209 m.swapRows(d,i);
01210 r.swapRows(d,i);
01211
01212 return;
01213 }
01214
01215 }
01216
01217 }
01218
01219 }