00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "config.hpp"
00014
00015 #if !defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE) || \
00016 defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_MATRIX)
00017
00018 #include <cstddef>
00019 #include <list>
00020 #include <sstream>
00021
00022 #include "matrix.hpp"
00023 #include "vector.hpp"
00024
00025 #include "_utility.hpp"
00026
00027
00028 namespace Arageli
00029 {
00030
00031
00032 template <typename T, bool REFCNT>
00033 matrix<T, REFCNT> inverse (const matrix<T, REFCNT>& A);
00034
00035
00036 template <typename T, bool REFCNT>
00037 void matrix<T, REFCNT>::assign_fromstr (const char* s)
00038 {
00039 std::istringstream buf(s);
00040 static_cast<std::istream&>(buf) >> *this;
00041 if(!buf && !buf.eof())
00042 throw incorrect_string(s);
00043 }
00044
00045
00046 template <typename T, bool REFCNT>
00047 template <typename Val>
00048 void matrix<T, REFCNT>::assign_fromval
00049 (size_type rows_a, size_type cols_a, const Val& val)
00050 {
00051
00052 resize(rows_a, cols_a);
00053 std::fill(begin(), end(), val);
00054 }
00055
00056
00057 template <typename T, bool REFCNT>
00058 template <typename Seq>
00059 void matrix<T, REFCNT>::assign_fromseq
00060 (size_type rows_a, size_type cols_a, Seq seq)
00061 {
00062
00063 resize(rows_a, cols_a);
00064 for(iterator i = begin(); i != end(); ++i)
00065 *i = *seq++;
00066 }
00067
00068
00069 template <typename T, bool REFCNT>
00070 template <typename Val>
00071 void matrix<T, REFCNT>::assign_diag_fromval
00072 (size_type rows_a, size_type cols_a, const Val& val)
00073 {
00074
00075 assign_fromsize(rows_a, cols_a);
00076 size_type minsize = std::min(rows_a, cols_a);
00077 for(size_type i = 0; i < minsize; ++i)
00078 el(i, i) = val;
00079 }
00080
00081
00082 template <typename T, bool REFCNT>
00083 template <typename Seq>
00084 void matrix<T, REFCNT>::assign_diag_fromseq
00085 (size_type rows_a, size_type cols_a, Seq seq)
00086 {
00087
00088 assign_fromsize(rows_a, cols_a);
00089 size_type minsize = std::min(rows_a, cols_a);
00090 for(size_type i = 0; i < minsize; ++i)
00091 el(i, i) = *seq++;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 template <typename T, bool REFCNT>
00140 bool matrix<T, REFCNT>::is_null () const
00141 {
00142 for(size_type i = 0; i < size(); ++i)
00143 if(!Arageli::is_null(mem(i)))return false;
00144 return true;
00145 }
00146
00147
00148 template <typename T, bool REFCNT>
00149 bool matrix<T, REFCNT>::is_unit () const
00150 {
00151 if(is_empty())return false;
00152 if(!is_square())return false;
00153 if(!Arageli::is_unit(el(0, 0)))return false;
00154
00155 for(size_type i = 1; i < size();)
00156 {
00157 for(size_type j = 0; j < ncols(); ++j, ++i)
00158 if(!Arageli::is_null(mem(i)))return false;
00159 if(!Arageli::is_unit(mem(i++)))return false;
00160 }
00161
00162 return true;
00163 }
00164
00165
00166 template <typename T, bool REFCNT>
00167 bool matrix<T, REFCNT>::is_opposite_unit () const
00168 {
00169 if(is_empty())return false;
00170 if(!is_square())return false;
00171 if(!Arageli::is_opposite_unit(el(0, 0)))return false;
00172
00173 for(size_type i = 1; i < size();)
00174 {
00175 for(size_type j = 0; j < ncols(); ++j, ++i)
00176 if(!Arageli::is_null(mem(i)))return false;
00177 if(!Arageli::is_opposite_unit(mem(i++)))return false;
00178 }
00179
00180 return true;
00181 }
00182
00183
00184 template <typename T, bool REFCNT>
00185 matrix<T, REFCNT>& matrix<T, REFCNT>::inverse ()
00186 { *this = Arageli::inverse(*this); }
00187
00188
00189 template <typename T, bool REFCNT>
00190 matrix<T, REFCNT>& matrix<T, REFCNT>::each_inverse ()
00191 {
00192 for(size_type i = 0; i < size(); ++i)
00193 Arageli::inverse(&mem(i));
00194 return *this;
00195 }
00196
00197
00198 #define _ARAGELI_MATRIX_OPERATOR_ASSIGN_1(OPER, MNEM) \
00199 template <typename T1, bool REFCNT1> \
00200 template <typename T2> \
00201 matrix<T1, REFCNT1>& matrix<T1, REFCNT1>::MNEM##_scalar \
00202 (const T2& x) \
00203 { \
00204 if(is_empty())return *this; \
00205 \
00206 \
00207 iterator i = begin(), iend = end(); \
00208 for(; i < iend; ++i) \
00209 *i OPER x; \
00210 \
00211 return *this; \
00212 } \
00213 \
00214 template <typename T1, bool REFCNT1> \
00215 template <typename T2> \
00216 matrix<T1, REFCNT1>& matrix<T1, REFCNT1>::each_##MNEM##_matrix \
00217 (const T2& x) \
00218 { \
00219 ARAGELI_ASSERT_0(x.nrows() == nrows()); \
00220 ARAGELI_ASSERT_0(x.ncols() == ncols()); \
00221 if(is_empty())return *this; \
00222 \
00223 \
00224 iterator i1 = begin(), i1end = end(); \
00225 typename T2::const_iterator i2 = x.begin(); \
00226 for(; i1 < i1end; ++i1, ++i2) \
00227 *i1 OPER *i2; \
00228 \
00229 return *this; \
00230 }
00231
00232
00233 _ARAGELI_MATRIX_OPERATOR_ASSIGN_1(+=, add)
00234 _ARAGELI_MATRIX_OPERATOR_ASSIGN_1(-=, sub)
00235 _ARAGELI_MATRIX_OPERATOR_ASSIGN_1(*=, mul)
00236 _ARAGELI_MATRIX_OPERATOR_ASSIGN_1(/=, div);
00237 _ARAGELI_MATRIX_OPERATOR_ASSIGN_1(%=, mod);
00238 _ARAGELI_MATRIX_OPERATOR_ASSIGN_1(&=, bitand)
00239 _ARAGELI_MATRIX_OPERATOR_ASSIGN_1(|=, bitor)
00240 _ARAGELI_MATRIX_OPERATOR_ASSIGN_1(^=, bitxor)
00241 _ARAGELI_MATRIX_OPERATOR_ASSIGN_1(<<=, shl)
00242 _ARAGELI_MATRIX_OPERATOR_ASSIGN_1(>>=, shr)
00243
00244 #undef _ARAGELI_MATRIX_OPERATOR_ASSIGN_1
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 template <typename T1, bool REFCNT1>
00361 template <typename T2>
00362 matrix<T1, REFCNT1>& matrix<T1, REFCNT1>::mul_matrix
00363 (const T2& right)
00364 {
00365 ARAGELI_ASSERT_0(ncols() == right.nrows());
00366
00367 if(is_empty() && ncols() == right.ncols())return *this;
00368
00369 if
00370 (
00371 reinterpret_cast<const void*>(this) !=
00372 reinterpret_cast<const void*>(&right)
00373 )
00374 {
00375 matrix left;
00376 swap(left);
00377 assign_fromsize(left.nrows(), right.ncols());
00378
00379
00380
00381 for(size_type i = 0; i < nrows(); ++i)
00382 for(size_type j = 0; j < ncols(); ++j)
00383 for(size_type k = 0; k < left.ncols(); ++k)
00384 el(i, j) += left(i, k) * right(k, j);
00385 }
00386 else
00387 {
00388 ARAGELI_ASSERT_1(is_square());
00389 matrix arg(nrows());
00390 swap(arg);
00391
00392 for(size_type i = 0; i < nrows(); ++i)
00393 for(size_type j = 0; j < nrows(); ++j)
00394 for(size_type k = 0; k < nrows(); ++k)
00395 el(i, j) += arg(i, k) * arg(k, j);
00396 }
00397
00398 return *this;
00399 }
00400
00401
00402 template <typename T1, bool REFCNT1>
00403 template <typename T2>
00404 matrix<T1, REFCNT1>& matrix<T1, REFCNT1>::div_matrix
00405 (const T2& right)
00406 {
00407 try { *this *= Arageli::inverse(right); }
00408 catch(const matrix_is_singular&)
00409 { throw division_by_zero(); }
00410 return *this;
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 template <typename T1, bool REFCNT1>
00475 matrix<T1, REFCNT1>& matrix<T1, REFCNT1>::opposite ()
00476 {
00477 if(is_empty())return *this;
00478 unique();
00479
00480 for(size_type i = 0; i < size(); ++i)
00481 Arageli::opposite(&mem(i));
00482
00483 return *this;
00484 }
00485
00486
00487 template <typename T1, bool REFCNT1>
00488 void matrix<T1, REFCNT1>::transpose ()
00489 {
00490
00491 matrix<T1, true> t(ncols(), nrows(), fromsize);
00492
00493 for(size_type i = 0; i < nrows(); ++i)
00494 for(size_type j = 0; j < ncols(); ++j)
00495 t(j, i) = el(i, j);
00496
00497 swap(t);
00498 }
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549 template <typename T, bool REFCNT>
00550 void matrix<T, REFCNT>::insert_row (size_type pos, const T& val)
00551 {
00552 ARAGELI_ASSERT_0(pos <= nrows());
00553
00554 unique();
00555 mem().insert(begin() + pos*ncols(), ncols(), val);
00556 ++rep().rows;
00557 }
00558
00559
00560 template <typename T, bool REFCNT>
00561 template <typename T1, bool REFCNT1>
00562 void matrix<T, REFCNT>::insert_row
00563 (size_type pos, const vector<T1, REFCNT1>& vals)
00564 {
00565 ARAGELI_ASSERT_0(vals.size() >= ncols());
00566 ARAGELI_ASSERT_0(pos <= nrows());
00567
00568 unique();
00569 if(ncols() == 0 && nrows() == 0)resize(0, vals.size());
00570 mem().insert(begin() + pos*ncols(), vals.begin(), vals.begin() + ncols());
00571 ++rep().rows;
00572 }
00573
00574
00575 template <typename T, bool REFCNT>
00576 template <typename In>
00577 void matrix<T, REFCNT>::insert_row (size_type pos, In first)
00578 {
00579 ARAGELI_ASSERT_0(pos <= nrows());
00580
00581
00582
00583
00584 In last = std::advance(first, ncols());
00585
00586 unique();
00587 mem().insert(begin() + pos*ncols(), first, last);
00588 ++rep().rows;
00589 }
00590
00591
00592 template <typename T, bool REFCNT>
00593 void matrix<T, REFCNT>::insert_rows
00594 (size_type pos, size_type n, const T& val)
00595 {
00596 ARAGELI_ASSERT_0(pos <= nrows());
00597
00598
00599
00600 for(size_type i = pos; i < pos + n; ++i)
00601 insert_row(pos, val);
00602 }
00603
00604
00605 template <typename T, bool REFCNT>
00606 template <typename T1, bool REFCNT1>
00607 void matrix<T, REFCNT>::insert_rows
00608 (size_type pos, size_type n, const vector<T1, REFCNT1>& vals)
00609 {
00610 ARAGELI_ASSERT_0(pos <= nrows());
00611
00612
00613
00614 for(size_type i = pos; i < pos + n; ++i)
00615 insert_row(pos, vals);
00616 }
00617
00618
00619
00620 template <typename T, bool REFCNT>
00621 template <typename In>
00622 void matrix<T, REFCNT>::insert_rows
00623 (size_type pos, size_type n, In first)
00624 {
00625 ARAGELI_ASSERT_0(pos <= nrows());
00626
00627
00628
00629 for(size_type i = pos; i < pos + n; ++i)
00630 insert_row(pos, first);
00631 }
00632
00633
00634 template <typename T, bool REFCNT>
00635 void matrix<T, REFCNT>::erase_row (size_type pos)
00636 {
00637 ARAGELI_ASSERT_0(pos < nrows());
00638
00639 unique();
00640 mem().erase(begin() + pos*ncols(), begin() + (pos + 1)*ncols());
00641 --rep().rows;
00642 }
00643
00644
00645 template <typename T, bool REFCNT>
00646 void matrix<T, REFCNT>::erase_rows (size_type pos, size_type n)
00647 {
00648 ARAGELI_ASSERT_0(pos < nrows());
00649 ARAGELI_ASSERT_0(pos + n <= nrows());
00650
00651 unique();
00652 mem().erase(begin() + pos*ncols(), begin() + (pos + n)*ncols());
00653 rep().rows -= n;
00654 }
00655
00656 template <typename T, bool REFCNT>
00657 void matrix<T, REFCNT>::swap_rows (size_type xpos, size_type ypos)
00658 {
00659 ARAGELI_ASSERT_0(xpos < nrows());
00660 ARAGELI_ASSERT_0(ypos < nrows());
00661
00662 if(xpos == ypos)return;
00663
00664 std::swap_ranges
00665 (
00666 begin() + xpos*ncols(), begin() + (xpos + 1)*ncols(),
00667 begin() + ypos*ncols()
00668 );
00669 }
00670
00671
00672 template <typename T, bool REFCNT>
00673 template <typename T1>
00674 void matrix<T, REFCNT>::mult_row (size_type i, const T1& x)
00675 {
00676 ARAGELI_ASSERT_0(i < nrows());
00677
00678 unique();
00679 for(size_type j = i*ncols(); j < (i+1)*ncols(); ++j)
00680 mem(j) *= x;
00681 }
00682
00683
00684 template <typename T, bool REFCNT>
00685 template <typename T1>
00686 void matrix<T, REFCNT>::div_row (size_type i, const T1& x)
00687 {
00688 ARAGELI_ASSERT_0(i < nrows());
00689
00690 unique();
00691 size_type endpos = (i+1)*ncols();
00692 for(size_type j = i*ncols(); j < endpos; ++j)
00693 mem(j) /= x;
00694 }
00695
00696
00697 template <typename T, bool REFCNT>
00698 template <typename T1>
00699 void matrix<T, REFCNT>::mod_row (size_type i, const T1& x)
00700 {
00701 ARAGELI_ASSERT_0(i < nrows());
00702
00703 unique();
00704 size_type endpos = (i+1)*ncols();
00705 for(size_type j = i*ncols(); j < endpos; ++j)
00706 mem(j) = mod(mem(j), x);
00707 }
00708
00709
00710
00711 template <typename T, bool REFCNT>
00712 void matrix<T, REFCNT>::add_rows (size_type dstpos, size_type srcpos)
00713 {
00714 ARAGELI_ASSERT_0(dstpos < nrows());
00715 ARAGELI_ASSERT_0(srcpos < nrows());
00716 ARAGELI_ASSERT_0(srcpos != dstpos);
00717
00718 unique();
00719 size_type endpos = (srcpos+1)*ncols();
00720 for(size_type i = srcpos*ncols(), j = dstpos*ncols(); i < endpos; ++i, ++j)
00721 mem(j) += mem(i);
00722 }
00723
00724
00725
00726 template <typename T, bool REFCNT>
00727 void matrix<T, REFCNT>::sub_rows (size_type dstpos, size_type srcpos)
00728 {
00729 ARAGELI_ASSERT_0(dstpos < nrows());
00730 ARAGELI_ASSERT_0(srcpos < nrows());
00731 ARAGELI_ASSERT_0(srcpos != dstpos);
00732
00733 unique();
00734 size_type endpos = (srcpos+1)*ncols();
00735 for(size_type i = srcpos*ncols(), j = dstpos*ncols(); i < endpos; ++i, ++j)
00736 mem(j) -= mem(i);
00737 }
00738
00739
00740
00741 template <typename T, bool REFCNT>
00742 template <typename T2>
00743 void matrix<T, REFCNT>::addmult_rows
00744 (size_type dstpos, size_type srcpos, const T2& y)
00745 {
00746 ARAGELI_ASSERT_0(dstpos < nrows());
00747 ARAGELI_ASSERT_0(srcpos < nrows());
00748 ARAGELI_ASSERT_0(dstpos != srcpos);
00749
00750 unique();
00751 size_type endpos = (srcpos+1)*ncols();
00752 for(size_type i = srcpos*ncols(), j = dstpos*ncols(); i < endpos; ++i, ++j)
00753 mem(j) += y*mem(i);
00754 }
00755
00756
00757
00758 template <typename T, bool REFCNT>
00759 template <typename T1, typename T2>
00760 void matrix<T, REFCNT>::addmult_rows
00761 (
00762 size_type dstpos, const T1& x,
00763 size_type srcpos, const T2& y
00764 )
00765 {
00766 ARAGELI_ASSERT_0(dstpos < nrows());
00767 ARAGELI_ASSERT_0(srcpos < nrows());
00768 ARAGELI_ASSERT_0(dstpos != srcpos);
00769
00770 unique();
00771 size_type endpos = (srcpos+1)*ncols();
00772 for(size_type i = srcpos*ncols(), j = dstpos*ncols(); i < endpos; ++i, ++j)
00773 (mem(j) *= x) += y*mem(i);
00774 }
00775
00776
00777 template <typename T, bool REFCNT>
00778 template <typename T1, typename V, typename T2>
00779 void matrix<T, REFCNT>::addmult_rows
00780 (
00781 size_type dstpos, const T1& x,
00782 const V& srcvec, const T2& y
00783 )
00784 {
00785 ARAGELI_ASSERT_0(dstpos < nrows());
00786 ARAGELI_ASSERT_0(srcvec.size() == ncols());
00787
00788 unique();
00789 size_type endpos = ncols();
00790 for(size_type i = 0, j = dstpos*ncols(); i < endpos; ++i, ++j)
00791 (mem(j) *= x) += y*srcvec[i];
00792 }
00793
00794
00795
00796
00797 template <typename T, bool REFCNT>
00798 void matrix<T, REFCNT>::insert_col (size_type pos, const T& val)
00799 {
00800 ARAGELI_ASSERT_0(pos <= ncols());
00801
00802 unique();
00803 size_type oldsize = size();
00804
00805 if(oldsize == 0)
00806 {
00807 rep().cols++;
00808 return;
00809 }
00810
00811 mem().resize(oldsize + nrows());
00812
00813
00814
00815 iterator src = mem().begin() + oldsize;
00816 iterator dst = mem().end();
00817 ARAGELI_ASSERT_1(dst == src + nrows());
00818 iterator end = dst - (ncols() - pos);
00819
00820
00821 while(dst != end)*--dst = *--src;
00822
00823 ARAGELI_ASSERT_1(src != mem().begin());
00824 ARAGELI_ASSERT_1(src <= dst);
00825 *(--dst) = val;
00826 ARAGELI_ASSERT_1(dst - src == nrows() - 1);
00827
00828 size_type newncols = ncols() + 1;
00829 iterator endend = mem().begin() + pos + 1;
00830
00831 for(;;)
00832 {
00833 if(end == endend)break;
00834 end -= newncols;
00835 while(dst != end)*--dst = *--src;
00836 *(--dst) = val;
00837 }
00838
00839 ARAGELI_ASSERT_1(dst == src);
00840 ARAGELI_ASSERT_1(dst == mem().begin() + pos);
00841
00842 rep().cols++;
00843
00844
00846
00847
00848
00849
00850 }
00851
00852
00853 template <typename T, bool REFCNT>
00854 template <typename T1, bool REFCNT1>
00855 void matrix<T, REFCNT>::insert_col
00856 (size_type pos, const vector<T1, REFCNT1>& vals)
00857 {
00858 ARAGELI_ASSERT_0(pos <= ncols());
00859 ARAGELI_ASSERT_0(vals.size() >= nrows());
00860
00861 unique();
00862 if(ncols() == 0 && nrows() == 0)resize(vals.size(), 0);
00863 size_type oldsize = size();
00864
00865 if(oldsize == 0)
00866 {
00867 rep().cols++;
00868 return;
00869 }
00870
00871 mem().resize(oldsize + nrows());
00872
00873
00874
00875 iterator src = mem().begin() + oldsize;
00876 iterator dst = mem().end();
00877 ARAGELI_ASSERT_1(dst == src + nrows());
00878 iterator end = dst - (ncols() - pos);
00879
00880
00881 while(dst != end)*--dst = *--src;
00882
00883
00884 ARAGELI_ASSERT_1(src <= dst);
00885 typename vector<T1, REFCNT1>::const_iterator pval = vals.begin() + nrows();
00886 *(--dst) = *(--pval);
00887 ARAGELI_ASSERT_1(dst - src == nrows() - 1);
00888
00889 size_type newncols = ncols() + 1;
00890 iterator endend = mem().begin() + pos + 1;
00891
00892 for(;;)
00893 {
00894 if(end == endend)break;
00895 end -= newncols;
00896 while(dst != end)*--dst = *--src;
00897 *(--dst) = *(--pval);
00898 }
00899
00900 ARAGELI_ASSERT_1(dst == src);
00901 ARAGELI_ASSERT_1(dst == mem().begin() + pos);
00902 ARAGELI_ASSERT_1(pval == vals.begin());
00903
00904 rep().cols++;
00905
00906
00908
00909
00910
00911
00912 }
00913
00914
00915 template <typename T, bool REFCNT>
00916 template <typename In>
00917 void matrix<T, REFCNT>::insert_col (size_type pos, In first)
00918 {
00919 ARAGELI_ASSERT_0(pos <= ncols());
00920
00921 unique();
00922 size_type oldsize = size();
00923
00924 if(oldsize == 0)
00925 {
00926 rep().cols++;
00927 return;
00928 }
00929
00930 mem().resize(oldsize + nrows());
00931
00932
00933
00934 iterator src = mem().begin() + oldsize;
00935 iterator dst = mem().end();
00936 ARAGELI_ASSERT_1(dst == src + nrows());
00937 iterator end = dst - (ncols() - pos);
00938
00939
00940 while(dst != end)*--dst = *--src;
00941
00942 ARAGELI_ASSERT_1(src != mem().begin());
00943 ARAGELI_ASSERT_1(src <= dst);
00944
00945 --dst;
00946 ARAGELI_ASSERT_1(dst - src == nrows() - 1);
00947
00948 size_type newncols = ncols() + 1;
00949 iterator endend = mem().begin() + pos + 1;
00950
00951 for(;;)
00952 {
00953 if(end == endend)break;
00954 end -= newncols;
00955 while(dst != end)*--dst = *--src;
00956
00957 --dst;
00958 }
00959
00960 ARAGELI_ASSERT_1(dst == src);
00961 ARAGELI_ASSERT_1(dst == mem().begin() + pos);
00962
00963
00964 rep().cols++;
00965
00966 end = mem().end() - (newncols - pos) + 1;
00967 for(dst = begin() + pos; dst < end; dst += newncols)
00968 *dst = *first++;
00969
00970
00972
00973
00974
00975
00976 }
00977
00978
00979 template <typename T, bool REFCNT>
00980 void matrix<T, REFCNT>::insert_cols
00981 (size_type pos, size_type n, const T& val)
00982 {
00983 ARAGELI_ASSERT_0(pos <= ncols());
00984
00985
00986
00987 for(size_type i = pos; i < pos + n; ++i)
00988 insert_col(pos, val);
00989
00990
00992
00993
00994
00995
00996 }
00997
00998
00999 template <typename T, bool REFCNT>
01000 template <typename T1, bool REFCNT1>
01001 void matrix<T, REFCNT>::insert_cols
01002 (size_type pos, size_type n, const vector<T1, REFCNT1>& vals)
01003 {
01004 ARAGELI_ASSERT_0(pos <= ncols());
01005
01006
01007
01008 for(size_type i = pos; i < pos + n; ++i)
01009 insert_col(pos, vals);
01010
01011
01013
01014
01015
01016
01017 }
01018
01019
01020
01021 template <typename T, bool REFCNT>
01022 template <typename In>
01023 void matrix<T, REFCNT>::insert_cols
01024 (size_type pos, size_type n, In first)
01025 {
01026 ARAGELI_ASSERT_0(pos <= ncols());
01027
01028
01029
01030 for(size_type i = pos; i < pos + n; ++i)
01031 insert_col(pos, first);
01032
01033
01035
01036
01037
01038
01039 }
01040
01041
01042 template <typename T, bool REFCNT>
01043 void matrix<T, REFCNT>::erase_col (size_type pos)
01044 {
01045 ARAGELI_ASSERT_0(pos < ncols());
01046
01047 unique();
01048 size_type oldsize = size();
01049
01050 if(oldsize == 0)
01051 {
01052 rep().cols--;
01053 return;
01054 }
01055
01056 iterator dst = mem().begin() + pos;
01057 iterator src = dst + 1;
01058 size_type newncols = ncols() - 1;
01059 iterator endend = mem().end() - (ncols() - pos) + 1;
01060
01061 while(src != endend)
01062 {
01063 iterator end = src + newncols;
01064 while(src != end)*dst++ = *src++;
01065 ++src;
01066 }
01067
01068 iterator end = mem().end();
01069 while(src != end)*dst++ = *src++;
01070
01071 mem().resize(oldsize - nrows());
01072 rep().cols--;
01073
01075
01076
01077
01078
01079 }
01080
01081
01082 template <typename T, bool REFCNT>
01083 void matrix<T, REFCNT>::erase_cols (size_type pos, size_type n)
01084 {
01085 ARAGELI_ASSERT_0(pos < ncols());
01086 ARAGELI_ASSERT_0(pos + n <= ncols());
01087
01088 unique();
01089 size_type oldsize = size();
01090
01091 if(oldsize == 0)
01092 {
01093 rep().cols-=n;
01094 return;
01095 }
01096
01097 iterator dst = mem().begin() + pos;
01098 iterator src = dst + n;
01099 size_type newncols = ncols() - n;
01100 iterator endend = mem().end() - (newncols - pos);
01101
01102 while(src != endend)
01103 {
01104 iterator end = src + newncols;
01105 while(src != end)*dst++ = *src++;
01106 src += n;
01107 }
01108
01109 iterator end = mem().end();
01110 while(src != end)*dst++ = *src++;
01111
01112 mem().resize(oldsize - n*nrows());
01113 rep().cols -= n;
01114
01115
01117
01118
01119
01120
01121 }
01122
01123 template <typename T, bool REFCNT>
01124 void matrix<T, REFCNT>::swap_cols (size_type xpos, size_type ypos)
01125 {
01126 ARAGELI_ASSERT_0(xpos < ncols());
01127 ARAGELI_ASSERT_0(ypos < ncols());
01128
01129 if(xpos == ypos || is_empty())return;
01130
01131 unique();
01132
01133 iterator p1 = mem().begin() + xpos, p2 = mem().begin() + ypos;
01134 size_type nc = ncols();
01135 iterator end = mem().end() - (nc - xpos);
01136
01137 for(;;)
01138 {
01139 std::iter_swap(p1, p2);
01140 if(p1 == end)break;
01141 p1 += nc; p2 += nc;
01142 }
01143
01144 ARAGELI_ASSERT_1(mem().end() - (nc - ypos) == p2);
01145
01146
01148
01149
01150
01151
01152
01153
01154
01155 }
01156
01157
01158 template <typename T, bool REFCNT>
01159 template <typename T1>
01160 void matrix<T, REFCNT>::mult_col (size_type i, const T1& x)
01161 {
01162 ARAGELI_ASSERT_0(i < ncols());
01163
01164 if(is_empty())return;
01165
01166 unique();
01167
01168 iterator p = mem().begin() + i;
01169 size_type nc = ncols();
01170 iterator end = mem().end() - (nc - i);
01171
01172 for(;;)
01173 {
01174 *p *= x;
01175 if(p == end)break;
01176 p += nc;
01177 }
01178
01179
01181
01182
01183
01184
01185
01186
01187
01188 }
01189
01190
01191 template <typename T, bool REFCNT>
01192 template <typename T1>
01193 void matrix<T, REFCNT>::div_col (size_type i, const T1& x)
01194 {
01195 ARAGELI_ASSERT_0(i < ncols());
01196
01197 if(is_empty())return;
01198
01199 unique();
01200
01201 iterator p = mem().begin() + i;
01202 size_type nc = ncols();
01203 iterator end = mem().end() - (nc - i);
01204
01205 for(;;)
01206 {
01207 *p /= x;
01208 if(p == end)break;
01209 p += nc;
01210 }
01211 }
01212
01213
01214
01215 template <typename T, bool REFCNT>
01216 template <typename T1>
01217 void matrix<T, REFCNT>::mod_col (size_type i, const T1& x)
01218 {
01219 ARAGELI_ASSERT_0(i < ncols());
01220
01221 if(is_empty())return;
01222
01223 unique();
01224
01225 iterator p = mem().begin() + i;
01226 size_type nc = ncols();
01227 iterator end = mem().end() - (nc - i);
01228
01229 for(;;)
01230 {
01231 *p = mod(*p, x);
01232 if(p == end)break;
01233 p += nc;
01234 }
01235 }
01236
01237
01238
01239
01240 template <typename T, bool REFCNT>
01241 void matrix<T, REFCNT>::add_cols (size_type dstpos, size_type srcpos)
01242 {
01243 ARAGELI_ASSERT_0(dstpos < ncols());
01244 ARAGELI_ASSERT_0(srcpos < ncols());
01245 ARAGELI_ASSERT_0(srcpos != dstpos);
01246
01247 if(is_empty())return;
01248
01249 unique();
01250
01251 iterator p1 = mem().begin() + dstpos, p2 = mem().begin() + srcpos;
01252 size_type nc = ncols();
01253 iterator end = mem().end() - (nc - dstpos);
01254
01255 for(;;)
01256 {
01257 *p1 += *p2;
01258 if(p1 == end)break;
01259 p1 += nc; p2 += nc;
01260 }
01261
01262 ARAGELI_ASSERT_1(mem().end() - (nc - srcpos) == p2);
01263
01265
01266
01267
01268
01269
01270
01271
01272 }
01273
01274
01275
01276 template <typename T, bool REFCNT>
01277 void matrix<T, REFCNT>::sub_cols (size_type dstpos, size_type srcpos)
01278 {
01279 ARAGELI_ASSERT_0(dstpos < ncols());
01280 ARAGELI_ASSERT_0(srcpos < ncols());
01281 ARAGELI_ASSERT_0(srcpos != dstpos);
01282
01283 if(is_empty())return;
01284
01285 unique();
01286
01287 iterator p1 = mem().begin() + dstpos, p2 = mem().begin() + srcpos;
01288 size_type nc = ncols();
01289 iterator end = mem().end() - (nc - dstpos);
01290
01291 for(;;)
01292 {
01293 *p1 -= *p2;
01294 if(p1 == end)break;
01295 p1 += nc; p2 += nc;
01296 }
01297
01298 ARAGELI_ASSERT_1(mem().end() - (nc - srcpos) == p2);
01299
01301
01302
01303
01304
01305
01306
01307
01308 }
01309
01310
01311
01312 template <typename T, bool REFCNT>
01313 template <typename T2>
01314 void matrix<T, REFCNT>::addmult_cols
01315 (size_type dstpos, size_type srcpos, const T2& y)
01316 {
01317 ARAGELI_ASSERT_0(dstpos < ncols());
01318 ARAGELI_ASSERT_0(srcpos < ncols());
01319 ARAGELI_ASSERT_0(srcpos != dstpos);
01320
01321 if(is_empty())return;
01322
01323 unique();
01324
01325 iterator p1 = mem().begin() + dstpos, p2 = mem().begin() + srcpos;
01326 size_type nc = ncols();
01327 iterator end = mem().end() - (nc - dstpos);
01328
01329 for(;;)
01330 {
01331 *p1 += y*(*p2);
01332 if(p1 == end)break;
01333 p1 += nc; p2 += nc;
01334 }
01335
01336 ARAGELI_ASSERT_1(mem().end() - (nc - srcpos) == p2);
01337 }
01338
01339
01340
01341 template <typename T, bool REFCNT>
01342 template <typename T1, typename T2>
01343 void matrix<T, REFCNT>::addmult_cols
01344 (
01345 size_type dstpos, const T1& x,
01346 size_type srcpos, const T2& y
01347 )
01348 {
01349 ARAGELI_ASSERT_0(dstpos < ncols());
01350 ARAGELI_ASSERT_0(srcpos < ncols());
01351 ARAGELI_ASSERT_0(srcpos != dstpos);
01352
01353 if(is_empty())return;
01354
01355 unique();
01356
01357 iterator p1 = mem().begin() + dstpos, p2 = mem().begin() + srcpos;
01358 size_type nc = ncols();
01359 iterator end = mem().end() - (nc - dstpos);
01360
01361 for(;;)
01362 {
01363 *p1 = x*(*p1) + y*(*p2);
01364 if(p1 == end)break;
01365 p1 += nc; p2 += nc;
01366 }
01367
01368 ARAGELI_ASSERT_1(mem().end() - (nc - srcpos) == p2);
01369 }
01370
01371
01372 template <typename T, bool REFCNT>
01373 template <typename T1, typename V, typename T2>
01374 void matrix<T, REFCNT>::addmult_cols
01375 (
01376 size_type dstpos, const T1& x,
01377 const V& srcvec, const T2& y
01378 )
01379 {
01380 ARAGELI_ASSERT_0(dstpos < ncols());
01381 ARAGELI_ASSERT_0(srcvec.size() == nrows());
01382
01383 if(is_empty())return;
01384
01385 unique();
01386
01387 iterator p1 = mem().begin() + dstpos;
01388 typename V::const_iterator p2 = srcvec.begin();
01389 size_type nc = ncols();
01390 iterator end = mem().end() - (nc - dstpos);
01391
01392 for(;;)
01393 {
01394 *p1 = x*(*p1) + y*(*p2);
01395 if(p1 == end)break;
01396 p1 += nc; ++p2;
01397 }
01398
01399 ARAGELI_ASSERT_1(p2 == srcvec.end());
01400 }
01401
01402
01403 template <typename T, bool REFCNT>
01404 template <typename V>
01405 V& matrix<T, REFCNT>::copy_col
01406 (size_type i, V& res) const
01407 {
01408 ARAGELI_ASSERT_0(i < ncols());
01409 res.resize(nrows());
01410 for(size_type j = 0; j < nrows(); ++j)
01411 res[j] = el(j, i);
01412 return res;
01413 }
01414
01415
01416 template <typename T, bool REFCNT>
01417 template <typename SV, typename M>
01418 M& matrix<T, REFCNT>::copy_rows (const SV& sv, M& res) const
01419 {
01420 size_type nc = ncols();
01421 res.assign_fromsize(sv.size(), nc);
01422
01423 const_iterator data = begin();
01424 typename M::iterator resi = res.begin();
01425 typename SV::const_iterator svi = sv.begin(), svend = sv.end();
01426
01427 for(; svi != svend; ++svi)
01428 {
01429 size_type r = *svi;
01430 ARAGELI_ASSERT_0(r < nrows());
01431 resi = std::copy(data + r*nc, data + r*nc + nc, resi);
01432 }
01433
01434 return res;
01435 }
01436
01437
01438 template <typename T, bool REFCNT>
01439 template <typename SV>
01440 void matrix<T, REFCNT>::erase_rows (const SV& sv)
01441 {
01442 if(sv.is_empty())return;
01443
01444 SV svt = sv;
01445 typedef typename SV::iterator SViter;
01446 std::sort(svt.begin(), svt.end());
01447
01448 SViter
01449 svti = svt.begin(),
01450 svtend = std::unique(svti, svt.end());
01451
01452 size_type curerased = *svti, nc = ncols();
01453
01454 ARAGELI_ASSERT_0(*(svtend-1) < size());
01455 ARAGELI_ASSERT_0(curerased < size());
01456
01457 iterator
01458 thisdst = begin() + curerased*nc,
01459 thissrc = thisdst + nc,
01460 thisend = end();
01461
01462 for(;;)
01463 {
01464 ++svti;
01465
01466 if(svti != svtend && *svti == curerased+1)
01467 {
01468 ++curerased;
01469 ++svti;
01470 ARAGELI_ASSERT_0(thissrc != thisend);
01471 thissrc += nc;
01472 }
01473
01474 ARAGELI_ASSERT_1(thissrc != thisend || svti == svtend);
01475
01476 iterator tend =
01477 svti == svtend ?
01478 thisend : thissrc + (*svti - curerased - 1)*nc;
01479
01480 thisdst = std::copy(thissrc, tend, thisdst);
01481
01482 if(tend == thisend)
01483 break;
01484
01485 thissrc = tend + nc;
01486 ARAGELI_ASSERT_1(svti != svtend);
01487 curerased = *svti;
01488 }
01489
01490 ARAGELI_ASSERT_1(svti == svtend);
01491 ARAGELI_ASSERT_1(thisdst + (svtend - svt.begin())*nc == thisend);
01492 mem().erase(thisdst, thisend);
01493 ARAGELI_ASSERT_1(mem().size()%nc == 0);
01494 rep().rows = mem().size()/nc;
01495 }
01496
01497
01498 template <typename T, bool REFCNT>
01499 template <typename SV, typename M>
01500 M& matrix<T, REFCNT>::copy_cols (const SV& sv, M& res) const
01501 {
01502
01503
01504 res.assign_fromsize(nrows(), sv.size());
01505 typename SV::const_iterator svi = sv.begin(), svend = sv.end();
01506 size_type nr = nrows();
01507 typename M::size_type i = 0;
01508
01509 for(; svi != svend; ++svi, ++i)
01510 {
01511 size_type c = *svi;
01512 for(size_type r = 0; r < nr; ++r)
01513 res(r, i) = el(r, c);
01514 }
01515
01516 return res;
01517 }
01518
01519
01520 template <typename T, bool REFCNT>
01521 template <typename SV>
01522 void matrix<T, REFCNT>::erase_cols (const SV& sv)
01523 {
01524
01525
01526 if(sv.is_empty())return;
01527
01528 SV svt = sv;
01529 std::sort(svt.begin(), svt.end(), std::greater<typename SV::value_type>());
01530 svt.erase(std::unique(svt.begin(), svt.end()), svt.end());
01531
01532 for(typename SV::const_iterator i = svt.begin(); i < svt.end(); ++i)
01533 erase_col(*i);
01534 }
01535
01536
01537 template <typename T, bool REFCNT>
01538 template <typename RS, typename CS, typename M>
01539 M& matrix<T, REFCNT>::copy_submatrix (const RS& rs, const CS& cs, M& res) const
01540 {
01541
01542
01543 res.assign_fromsize(rs.size(), cs.size());
01544
01545 for(size_type i = 0; i < rs.size(); ++i)
01546 for(size_type j = 0; j < cs.size(); ++j)
01547 res(i, j) = el(rs[i], cs[j]);
01548
01549 return res;
01550 }
01551
01552
01553 template <typename T, bool REFCNT>
01554 template <typename RS, typename CS>
01555 void matrix<T, REFCNT>::erase_submatrix (const RS& rs, const CS& cs)
01556 {
01557 erase_rows(rs);
01558 erase_cols(cs);
01559 }
01560
01561
01562 template <typename T, bool REFCNT>
01563 bool matrix<T, REFCNT>::do_pack ()
01564 {
01565 ARAGELI_ASSERT_1(size() < capacity());
01566
01567 unique();
01568 Rep trep = rep();
01569 trep.swap(rep());
01570 }
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595 template
01596 <
01597 typename T1, bool REFCNT1,
01598 typename T2, bool REFCNT2
01599 >
01600 vector<T2, REFCNT2> operator*
01601 (
01602 const matrix<T1, REFCNT1>& m,
01603 const vector<T2, REFCNT2>& x
01604 )
01605 {
01606 ARAGELI_ASSERT_0(m.ncols() == x.size());
01607
01608 vector<T2, REFCNT2> res(m.nrows());
01609
01610 for(std::size_t i = 0; i < m.nrows(); ++i)
01611 {
01612 typename vector<T2, REFCNT2>::reference cur = res[i];
01613
01614 for(std::size_t j = 0; j < m.ncols(); ++j)
01615 cur += m(i, j)*x[j];
01616 }
01617
01618 return res;
01619 }
01620
01621
01622 template
01623 <
01624 typename T2, bool REFCNT2,
01625 typename T1, bool REFCNT1
01626 >
01627 vector<T2, REFCNT2> operator*
01628 (
01629 const vector<T2, REFCNT2>& x,
01630 const matrix<T1, REFCNT1>& m
01631 )
01632 {
01633 ARAGELI_ASSERT_0(m.nrows() == x.size());
01634
01635 vector<T2, REFCNT2> res(m.ncols());
01636
01637 for(std::size_t i = 0; i < m.ncols(); ++i)
01638 {
01639 typename vector<T2, REFCNT2>::reference cur = res[i];
01640
01641 for(std::size_t j = 0; j < m.nrows(); ++j)
01642 cur += m(j, i)*x[j];
01643 }
01644
01645 return res;
01646 }
01647
01648
01649 template <typename T, bool REFCNT>
01650 std::ostream& output_list
01651 (
01652 std::ostream& out,
01653 const matrix<T, REFCNT>& x,
01654 const char* first_bracket,
01655 const char* second_bracket,
01656 const char* row_separator,
01657 const char* first_row_bracket,
01658 const char* second_row_bracket,
01659 const char* col_separator
01660 )
01661 {
01662 out << first_bracket;
01663 typedef typename matrix<T, REFCNT>::size_type size_type;
01664
01665 if(!x.is_empty())
01666 {
01667 ARAGELI_ASSERT_0(x.ncols() && x.nrows());
01668
01669 out << first_row_bracket << x(0, 0);
01670 for(size_type j = 1; j < x.ncols(); ++j)
01671 out << col_separator << x(0, j);
01672 out << second_row_bracket;
01673
01674 for(size_type i = 1; i < x.nrows(); ++i)
01675 {
01676 out << row_separator << first_row_bracket << x(i, 0);
01677 for(size_type j = 1; j < x.ncols(); ++j)
01678 out << col_separator << x(i, j);
01679 out << second_row_bracket;
01680 }
01681 }
01682
01683 out << second_bracket;
01684 return out;
01685 }
01686
01687
01688 template <typename T, bool REFCNT>
01689 std::istream& input_list
01690 (
01691 std::istream& in,
01692 matrix<T, REFCNT>& x,
01693 const char* first_bracket,
01694 const char* second_bracket,
01695 const char* row_separator,
01696 const char* first_row_bracket,
01697 const char* second_row_bracket,
01698 const char* col_separator
01699 )
01700 {
01701 ARAGELI_ASSERT_0(_Internal::is_not_contains_spaces(first_bracket));
01702 ARAGELI_ASSERT_0(_Internal::is_not_contains_spaces(second_bracket));
01703 ARAGELI_ASSERT_0(_Internal::is_not_contains_spaces(row_separator));
01704 ARAGELI_ASSERT_0(_Internal::is_not_contains_spaces(first_row_bracket));
01705 ARAGELI_ASSERT_0(_Internal::is_not_contains_spaces(second_row_bracket));
01706 ARAGELI_ASSERT_0(_Internal::is_not_contains_spaces(col_separator));
01707
01708 if(!_Internal::read_literal(in, first_bracket))
01709 {
01710 in.clear(std::ios_base::failbit);
01711 return in;
01712 }
01713
01714 if(*second_bracket && _Internal::read_literal(in, second_bracket))
01715 {
01716 x.assign_fromsize(0, 0);
01717 return in;
01718 }
01719
01720 typedef std::list<vector<T, true> > Buf;
01721 Buf buf;
01722 std::size_t cols;
01723
01724 do
01725 {
01726 vector<T, false> tmp;
01727
01728 input_list
01729 (
01730 in, tmp, first_row_bracket,
01731 second_row_bracket, col_separator
01732 );
01733
01734 if(!in)
01735 {
01736 in.clear(std::ios_base::badbit);
01737 return in;
01738 }
01739
01740 if(buf.empty())
01741 cols = tmp.size();
01742 else if(cols != tmp.size())
01743 {
01744 in.clear(std::ios_base::badbit);
01745 return in;
01746 }
01747
01748 buf.push_back(tmp);
01749
01750 }while(_Internal::read_literal(in, row_separator));
01751
01752
01753 if(!_Internal::read_literal(in, second_bracket))
01754 {
01755 in.clear(std::ios_base::badbit);
01756 return in;
01757 }
01758
01759 x.assign_fromsize(buf.size(), cols);
01760 typename matrix<T, REFCNT>::iterator j = x.begin();
01761
01762 for(typename Buf::iterator i = buf.begin(); i != buf.end(); ++i)
01763 {
01764 ARAGELI_ASSERT_1(i->size() == cols);
01765 j = std::copy(i->begin(), i->end(), j);
01766 }
01767
01768 ARAGELI_ASSERT_1(j == x.end());
01769
01770 return in;
01771 }
01772
01773
01774 template <typename T, bool REFCNT>
01775 std::ostream& output_aligned
01776 (
01777 std::ostream& out,
01778 const matrix<T, REFCNT>& x,
01779 const char* left_col,
01780 const char* right_col,
01781 const char* inter_col
01782 )
01783 {
01784 if(x.is_empty())
01785 {
01786 out << left_col << right_col << '\n';
01787 return out;
01788 }
01789
01790 std::vector<std::string> buf(x.size());
01791 std::vector<std::size_t> maxlens(x.ncols());
01792 std::size_t ii = 0;
01793
01794 for(std::size_t j = 0; j < x.ncols(); ++j)
01795 {
01796 std::size_t maxlen = 0;
01797
01798 for(std::size_t i = 0; i < x.nrows(); ++i, ++ii)
01799 {
01800 std::ostringstream strbuf;
01801 strbuf.copyfmt(out);
01802 strbuf << x(i, j);
01803 buf[ii] = strbuf.str();
01804
01805 if(buf[ii].length() > maxlen)
01806 maxlen = buf[ii].length();
01807 }
01808
01809 maxlens[j] = maxlen;
01810 }
01811
01812
01813
01814 for(std::size_t i = 0; i < x.nrows(); ++i)
01815 {
01816 out << left_col;
01817
01818 std::string& str = buf[i];
01819 std::size_t numspace = maxlens[0] - str.length();
01820
01821 out
01822 << std::string(numspace/2, ' ')
01823 << str << std::string(numspace - numspace/2, ' ');
01824
01825 for(std::size_t j = 1; j < x.ncols(); ++j)
01826 {
01827 std::string& str = buf[j*x.nrows() + i];
01828 std::size_t numspace = maxlens[j] - str.length();
01829
01830 out
01831 << inter_col << std::string(numspace/2, ' ')
01832 << str << std::string(numspace - numspace/2, ' ');
01833 }
01834
01835 out << right_col << '\n';
01836 }
01837
01838 return out;
01839 }
01840
01841
01842 template
01843 <
01844 typename T1, bool REFCNT1,
01845 typename T2, bool REFCNT2
01846 >
01847 std::ostream& output_aligned_ver_pair
01848 (
01849 std::ostream& out,
01850 const matrix<T1, REFCNT1>& m1,
01851 const matrix<T2, REFCNT2>& m2,
01852 const char* left_col,
01853 const char* right_col,
01854 const char* inter_col,
01855 const char* hsplitter
01856 )
01857 {
01858 ARAGELI_ASSERT_0(m1.ncols() == m2.ncols());
01859
01860 if(m1.is_empty() && m2.is_empty())
01861 {
01862 out << left_col << right_col << '\n';
01863 return out;
01864 }
01865
01866 std::vector<std::string> buf(m1.size() + m2.size());
01867 std::vector<std::size_t> maxlens(m1.ncols());
01868 std::size_t ii = 0;
01869
01870 for(std::size_t j = 0; j < m1.ncols(); ++j)
01871 {
01872 std::size_t maxlen = 0;
01873
01874 for(std::size_t i = 0; i < m1.nrows(); ++i, ++ii)
01875 {
01876 std::string& curbuf = buf[ii];
01877
01878 std::ostringstream strbuf;
01879 strbuf << m1(i, j);
01880 curbuf = strbuf.str();
01881
01882 std::size_t curlen = curbuf.length();
01883 if(curlen > maxlen)maxlen = curlen;
01884 }
01885
01886 for(std::size_t i = 0; i < m2.nrows(); ++i, ++ii)
01887 {
01888 std::string& curbuf = buf[ii];
01889
01890 std::ostringstream strbuf;
01891 strbuf << m2(i, j);
01892 curbuf = strbuf.str();
01893
01894 std::size_t curlen = curbuf.length();
01895 if(curlen > maxlen)maxlen = curlen;
01896 }
01897
01898 maxlens[j] = maxlen;
01899 }
01900
01901
01902 for(std::size_t i = 0; i < m1.nrows(); ++i)
01903 {
01904 out << left_col;
01905
01906 std::string& str = buf[i];
01907 std::size_t numspace = maxlens[0] - str.length();
01908
01909 out
01910 << std::string(numspace/2, ' ')
01911 << str << std::string(numspace - numspace/2, ' ');
01912
01913 for(std::size_t j = 1; j < m1.ncols(); ++j)
01914 {
01915 std::string& str = buf[j*(m1.nrows() + m2.nrows()) + i];
01916 std::size_t numspace = maxlens[j] - str.length();
01917
01918 out
01919 << inter_col << std::string(numspace/2, ' ')
01920 << str << std::string(numspace - numspace/2, ' ');
01921 }
01922
01923 out << right_col << '\n';
01924 }
01925
01926 ARAGELI_ASSERT_1(m1.ncols());
01927
01928 std::size_t width = (m1.ncols() - 1)*std::strlen(inter_col);
01929 width = std::accumulate(maxlens.begin(), maxlens.end(), width);
01930 std::size_t splitter_len = std::strlen(hsplitter);
01931 std::size_t insplit = width/splitter_len;
01932
01933 out << left_col;
01934
01935 for(std::size_t i = 0; i < insplit; ++i)
01936 out << hsplitter;
01937
01938 insplit = width%splitter_len;
01939
01940 for(std::size_t i = 0; i < insplit; ++i)
01941 out << hsplitter[i];
01942
01943 out << right_col << '\n';
01944
01945 for(std::size_t i = 0; i < m2.nrows(); ++i)
01946 {
01947 out << left_col;
01948
01949 std::string& str = buf[i + + m1.nrows()];
01950 std::size_t numspace = maxlens[0] - str.length();
01951
01952 out
01953 << std::string(numspace/2, ' ')
01954 << str << std::string(numspace - numspace/2, ' ');
01955
01956 for(std::size_t j = 1; j < m2.ncols(); ++j)
01957 {
01958 std::string& str = buf[j*(m1.nrows() + m2.nrows()) + i + m1.nrows()];
01959 std::size_t numspace = maxlens[j] - str.length();
01960
01961 out
01962 << inter_col << std::string(numspace/2, ' ')
01963 << str << std::string(numspace - numspace/2, ' ');
01964 }
01965
01966 out << right_col << '\n';
01967 }
01968
01969 return out;
01970 }
01971
01972
01973 template
01974 <
01975 typename T1, bool REFCNT1,
01976 typename T2, bool REFCNT2
01977 >
01978 std::ostream& output_aligned_hor_pair
01979 (
01980 std::ostream& out,
01981 const matrix<T1, REFCNT1>& m1,
01982 const matrix<T2, REFCNT2>& m2,
01983 const char* left_col,
01984 const char* right_col,
01985 const char* inter_col,
01986 const char* vsplitter
01987 )
01988 {
01989 ARAGELI_ASSERT_0(m1.nrows() == m2.nrows());
01990
01991 if(m1.is_empty() && m2.is_empty())
01992 {
01993 out << left_col << right_col << '\n';
01994 return out;
01995 }
01996
01997 std::vector<std::string> buf1(m1.size());
01998 std::vector<std::size_t> maxlens1(m1.ncols());
01999 std::size_t ii = 0;
02000
02001 for(std::size_t j = 0; j < m1.ncols(); ++j)
02002 {
02003 std::size_t maxlen = 0;
02004
02005 for(std::size_t i = 0; i < m1.nrows(); ++i, ++ii)
02006 {
02007 std::ostringstream strbuf;
02008 strbuf << m1(i, j);
02009 buf1[ii] = strbuf.str();
02010
02011 if(buf1[ii].length() > maxlen)
02012 maxlen = buf1[ii].length();
02013 }
02014
02015 maxlens1[j] = maxlen;
02016 }
02017
02018 std::vector<std::string> buf2(m2.size());
02019 std::vector<std::size_t> maxlens2(m1.ncols());
02020 ii = 0;
02021
02022 for(std::size_t j = 0; j < m2.ncols(); ++j)
02023 {
02024 std::size_t maxlen = 0;
02025
02026 for(std::size_t i = 0; i < m2.nrows(); ++i, ++ii)
02027 {
02028 std::ostringstream strbuf;
02029 strbuf << m2(i, j);
02030 buf2[ii] = strbuf.str();
02031
02032 if(buf2[ii].length() > maxlen)
02033 maxlen = buf2[ii].length();
02034 }
02035
02036 maxlens2[j] = maxlen;
02037 }
02038
02039
02040 for(std::size_t i = 0; i < m1.nrows(); ++i)
02041 {
02042 out << left_col;
02043
02044 {
02045 std::string& str = buf1[i];
02046 std::size_t numspace = maxlens1[0] - str.length();
02047
02048 out
02049 << std::string(numspace/2, ' ')
02050 << str << std::string(numspace - numspace/2, ' ');
02051
02052 for(std::size_t j = 1; j < m1.ncols(); ++j)
02053 {
02054 std::string& str = buf1[j*m1.nrows() + i];
02055 std::size_t numspace = maxlens1[j] - str.length();
02056
02057 out
02058 << inter_col << std::string(numspace/2, ' ')
02059 << str << std::string(numspace - numspace/2, ' ');
02060 }
02061 }
02062
02063 out << vsplitter;
02064
02065 {
02066 std::string& str = buf2[i];
02067 std::size_t numspace = maxlens2[0] - str.length();
02068
02069 out
02070 << std::string(numspace/2, ' ')
02071 << str << std::string(numspace - numspace/2, ' ');
02072
02073 for(std::size_t j = 1; j < m2.ncols(); ++j)
02074 {
02075 std::string& str = buf2[j*m2.nrows() + i];
02076 std::size_t numspace = maxlens2[j] - str.length();
02077
02078 out
02079 << inter_col << std::string(numspace/2, ' ')
02080 << str << std::string(numspace - numspace/2, ' ');
02081 }
02082 }
02083
02084 out << right_col << '\n';
02085 }
02086
02087 return out;
02088 }
02089
02090
02091 template
02092 <
02093 typename T1, bool REFCNT1,
02094 typename T2, bool REFCNT2,
02095 typename T3, bool REFCNT3
02096 >
02097 std::ostream& output_aligned_corner_triplet_br
02098 (
02099 std::ostream& out,
02100 const matrix<T1, REFCNT1>& m1,
02101 const matrix<T2, REFCNT2>& m2,
02102 const matrix<T3, REFCNT3>& m3,
02103 const char* left_col,
02104 const char* right_col,
02105 const char* inter_col,
02106 const char* vsplitter,
02107 const char* hsplitter
02108 )
02109 {
02110
02111
02112
02113
02114
02115
02116 ARAGELI_ASSERT_0(m1.ncols() == m2.ncols());
02117 ARAGELI_ASSERT_0(m3.nrows() == m2.nrows());
02118
02119 if(m1.is_empty() && m2.is_empty())
02120 {
02121 out << left_col << right_col;
02122 return out;
02123 }
02124
02125 std::stringstream strbuf;
02126
02127 output_aligned_ver_pair(strbuf, m1, m2, "", "", inter_col, hsplitter);
02128 std::string m12str = strbuf.str();
02129 strbuf.str("");
02130
02131 output_aligned(strbuf, m3, "", "", inter_col);
02132 std::string m3str = strbuf.str();
02133 strbuf.str("");
02134
02135 std::size_t width3 = m3str.find('\n');
02136 ARAGELI_ASSERT_1(width3 < m3str.length());
02137
02138 std::string tlspace(width3 + std::strlen(vsplitter), ' ');
02139
02140 std::size_t cur12 = 0, cur3 = 0;
02141
02142 for(std::size_t i = 0; i < m1.nrows() + 1; ++i)
02143 {
02144 std::size_t end12 = m12str.find('\n', cur12);
02145 ARAGELI_ASSERT_1(end12 < m12str.length());
02146
02147 out
02148 << left_col << tlspace
02149 << m12str.substr(cur12, end12 - cur12)
02150 << right_col << '\n';
02151
02152 cur12 = end12 + 1;
02153 }
02154
02155 for(std::size_t i = 0; i < m2.nrows(); ++i)
02156 {
02157 std::size_t end3 = m3str.find('\n', cur3);
02158 ARAGELI_ASSERT_1(end3 < m3str.length());
02159
02160 std::size_t end12 = m12str.find('\n', cur12);
02161 ARAGELI_ASSERT_1(end12 < m12str.length());
02162
02163 out
02164 << left_col
02165 << m3str.substr(cur3, end3 - cur3)
02166 << vsplitter
02167 << m12str.substr(cur12, end12 - cur12)
02168 << right_col << '\n';
02169
02170 cur12 = end12 + 1;
02171 cur3 = end3 + 1;
02172 }
02173
02174 return out;
02175 }
02176
02177
02178 template <typename T, bool REFCNT>
02179 std::istream& input_polynom_internal
02180 (std::istream& in, matrix<T, REFCNT>& x)
02181 {
02182 char ch = 0;
02183 in >> ch;
02184 if(!in && !in.eof() || ch != '+' && ch != '-')return in;
02185 matrix<T, REFCNT> res;
02186 input_list(in, res);
02187 if(!in && !in.eof())return in;
02188 if(ch == '-')res.opposite();
02189 x = res;
02190 return in;
02191 }
02192
02193
02194 }
02195
02196
02197 #else
02198
02199 #include "matrix.hpp"
02200
02201
02202 namespace Arageli
02203 {
02204
02205 const char* matrix_output_list_first_bracket_default = "(";
02206 const char* matrix_output_list_second_bracket_default = ")";
02207 const char* matrix_output_list_row_separator_default = ", ";
02208 const char* matrix_output_list_first_row_bracket_default = "(";
02209 const char* matrix_output_list_second_row_bracket_default = ")";
02210 const char* matrix_output_list_col_separator_default = ", ";
02211 const char* matrix_input_list_first_bracket_default = "(";
02212 const char* matrix_input_list_second_bracket_default = ")";
02213 const char* matrix_input_list_row_separator_default = ",";
02214 const char* matrix_input_list_first_row_bracket_default = "(";
02215 const char* matrix_input_list_second_row_bracket_default = ")";
02216 const char* matrix_input_list_col_separator_default = ",";
02217 const char* matrix_output_aligned_left_col_default = "||";
02218 const char* matrix_output_aligned_right_col_default = "||";
02219 const char* matrix_output_aligned_inter_col_default = " ";
02220
02221 }
02222
02223
02224 #endif // #ifndef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE