00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00044 #ifndef SCYTHE_MATRIX_H
00045 #define SCYTHE_MATRIX_H
00046
00047
00048 #include <iostream>
00049 #include <iomanip>
00050 #include <string>
00051 #include <sstream>
00052 #include <fstream>
00053 #include <iterator>
00054 #include <algorithm>
00055
00056 #include <functional>
00057 #include <list>
00058
00059 #ifdef SCYTHE_COMPILE_DIRECT
00060 #include "defs.h"
00061 #include "algorithm.h"
00062 #include "error.h"
00063 #include "datablock.h"
00064 #include "matrix_random_access_iterator.h"
00065 #include "matrix_forward_iterator.h"
00066 #include "matrix_bidirectional_iterator.h"
00067 #ifdef SCYTHE_LAPACK
00068 #include "lapack.h"
00069 #endif
00070 #else
00071 #include "scythestat/defs.h"
00072 #include "scythestat/algorithm.h"
00073 #include "scythestat/error.h"
00074 #include "scythestat/datablock.h"
00075 #include "scythestat/matrix_random_access_iterator.h"
00076 #include "scythestat/matrix_forward_iterator.h"
00077 #include "scythestat/matrix_bidirectional_iterator.h"
00078 #ifdef SCYTHE_LAPACK
00079 #include "scythestat/lapack.h"
00080 #endif
00081 #endif
00082
00083 namespace scythe {
00084
00085 namespace {
00086
00087 typedef unsigned int uint;
00088 }
00089
00090
00091
00092
00093
00094 template <typename T_type, matrix_order ORDER, matrix_style STYLE,
00095 matrix_order L_ORDER, matrix_style L_STYLE,
00096 matrix_order R_ORDER, matrix_style R_STYLE>
00097 Matrix<T_type, ORDER, STYLE>
00098 operator* (const Matrix<T_type, L_ORDER, L_STYLE>& lhs,
00099 const Matrix<T_type, R_ORDER, R_STYLE>& rhs);
00100
00101
00102 template <matrix_order L_ORDER, matrix_style L_STYLE,
00103 matrix_order R_ORDER, matrix_style R_STYLE, typename T_type>
00104 Matrix<T_type, L_ORDER, Concrete>
00105 operator* (const Matrix<T_type, L_ORDER, L_STYLE>& lhs,
00106 const Matrix<T_type, R_ORDER, R_STYLE>& rhs);
00107
00108
00109 template <typename T_type, matrix_order ORDER, matrix_style STYLE>
00110 class Matrix;
00111
00152 template<typename T_elem, typename T_iter,
00153 matrix_order O, matrix_style S>
00154 class ListInitializer {
00155
00156 template <class T, matrix_order OO, matrix_style SS>
00157 friend class Matrix;
00158
00159 public:
00160 ListInitializer (T_elem val, T_iter begin, T_iter end,
00161 Matrix<T_elem,O,S>* matrix)
00162 : vals_ (),
00163 iter_ (begin),
00164 end_ (end),
00165 matrix_ (matrix),
00166 populated_ (false)
00167 {
00168 vals_.push_back(val);
00169 }
00170
00171 ~ListInitializer ()
00172 {
00173 if (! populated_)
00174 populate();
00175 }
00176
00177 ListInitializer &operator, (T_elem x)
00178 {
00179 vals_.push_back(x);
00180 return *this;
00181 }
00182
00183 private:
00184 void populate ()
00185 {
00186 typename std::list<T_elem>::iterator vi = vals_.begin();
00187
00188 while (iter_ < end_) {
00189 if (vi == vals_.end())
00190 vi = vals_.begin();
00191 *iter_ = *vi;
00192 ++iter_; ++vi;
00193 }
00194
00195 populated_ = true;
00196 }
00197
00198 std::list<T_elem> vals_;
00199 T_iter iter_;
00200 T_iter end_;
00201 Matrix<T_elem, O, S>* matrix_;
00202 bool populated_;
00203 };
00204
00219 template <matrix_order ORDER = Col, matrix_style STYLE = Concrete>
00220 class Matrix_base
00221 {
00222 protected:
00223
00224
00225
00226 Matrix_base ()
00227 : rows_ (0),
00228 cols_ (0),
00229 rowstride_ (0),
00230 colstride_ (0),
00231 storeorder_ (ORDER)
00232 {}
00233
00234
00235 Matrix_base (uint rows, uint cols)
00236 : rows_ (rows),
00237 cols_ (cols),
00238 storeorder_ (ORDER)
00239 {
00240 if (ORDER == Col) {
00241 rowstride_ = 1;
00242 colstride_ = rows;
00243 } else {
00244 rowstride_ = cols;
00245 colstride_ = 1;
00246 }
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 Matrix_base (const Matrix_base &m)
00259 : rows_ (m.rows()),
00260 cols_ (m.cols()),
00261 rowstride_ (m.rowstride()),
00262 colstride_ (m.colstride())
00263 {
00264 if (STYLE == View)
00265 storeorder_ = m.storeorder();
00266 else
00267 storeorder_ = ORDER;
00268 }
00269
00270 template <matrix_order O, matrix_style S>
00271 Matrix_base (const Matrix_base<O, S> &m)
00272 : rows_ (m.rows()),
00273 cols_ (m.cols())
00274 {
00275 if (STYLE == View) {
00276 storeorder_ = m.storeorder();
00277 rowstride_ = m.rowstride();
00278 colstride_ = m.colstride();
00279 } else {
00280 storeorder_ = ORDER;
00281 if (ORDER == Col) {
00282 rowstride_ = 1;
00283 colstride_ = rows_;
00284 } else {
00285 rowstride_ = cols_;
00286 colstride_ = 1;
00287 }
00288 }
00289 }
00290
00291
00292 template <matrix_order O, matrix_style S>
00293 Matrix_base (const Matrix_base<O, S> &m,
00294 uint x1, uint y1, uint x2, uint y2)
00295 : rows_ (x2 - x1 + 1),
00296 cols_ (y2 - y1 + 1),
00297 rowstride_ (m.rowstride()),
00298 colstride_ (m.colstride()),
00299 storeorder_ (m.storeorder())
00300 {
00301
00302
00303
00304
00305
00306
00307
00308 if (STYLE == Concrete) {
00309 SCYTHE_THROW(scythe_style_error,
00310 "Tried to construct a concrete submatrix (Matrix_base)!");
00311 }
00312 }
00313
00314
00315
00316
00317 ~Matrix_base ()
00318 {}
00319
00320
00321
00322
00323
00324 Matrix_base& operator=(const Matrix_base& m)
00325 {
00326 SCYTHE_THROW(scythe_unexpected_default_error,
00327 "Unexpected call to Matrix_base default assignment operator");
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 template <matrix_order O, matrix_style S>
00342 inline void mimic (const Matrix_base<O, S> &m)
00343 {
00344 rows_ = m.rows();
00345 cols_ = m.cols();
00346 rowstride_ = m.rowstride();
00347 colstride_ = m.colstride();
00348 storeorder_ = m.storeorder();
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 inline void resize (uint rows, uint cols)
00362 {
00363 rows_ = rows;
00364 cols_ = cols;
00365
00366 if (ORDER == Col) {
00367 rowstride_ = 1;
00368 colstride_ = rows;
00369 } else {
00370 rowstride_ = cols;
00371 colstride_ = 1;
00372 }
00373
00374 storeorder_ = ORDER;
00375 }
00376
00377 public:
00378
00379
00386 inline uint size () const
00387 {
00388 return (rows() * cols());
00389 }
00390
00396 inline uint rows() const
00397 {
00398 return rows_;
00399 }
00400
00406 inline uint cols () const
00407 {
00408 return cols_;
00409 }
00410
00418 inline matrix_order order() const
00419 {
00420 return ORDER;
00421 }
00422
00430 inline matrix_style style() const
00431 {
00432 return STYLE;
00433 }
00434
00447 inline matrix_order storeorder () const
00448 {
00449 return storeorder_;
00450 }
00451
00458 inline uint rowstride () const
00459 {
00460 return rowstride_;
00461 }
00462
00469 inline uint colstride () const
00470 {
00471 return colstride_;
00472 }
00473
00481 inline uint max_size () const
00482 {
00483 return UINT_MAX;
00484 }
00485
00490 inline bool isScalar () const
00491 {
00492 return (rows() == 1 && cols() == 1);
00493 }
00494
00500 inline bool isRowVector () const
00501 {
00502 return (rows() == 1);
00503 }
00504
00510 inline bool isColVector () const
00511 {
00512 return (cols() == 1);
00513 }
00514
00520 inline bool isVector () const
00521 {
00522 return (cols() == 1 || rows() == 1);
00523 }
00524
00532 inline bool isSquare () const
00533 {
00534 return (cols() == rows());
00535 }
00536
00542 inline bool isNull () const
00543 {
00544 return (rows() == 0);
00545 }
00546
00554 inline bool empty () const
00555 {
00556 return (rows() == 0);
00557 }
00558
00559
00560
00561
00576 inline bool inRange (uint i) const
00577 {
00578 return (i < size());
00579 }
00580
00596 inline bool inRange (uint i, uint j) const
00597 {
00598 return (i < rows() && j < cols());
00599 }
00600
00601 protected:
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 inline uint index (uint i) const
00616 {
00617 if (STYLE == View) {
00618 if (ORDER == Col) {
00619 uint col = i / rows();
00620 uint row = i % rows();
00621 return (index(row, col));
00622 } else {
00623 uint row = i / cols();
00624 uint col = i % cols();
00625 return (index(row, col));
00626 }
00627 } else
00628 return(i);
00629 }
00630
00631
00632 inline uint index (uint row, uint col) const
00633 {
00634 if (STYLE == Concrete) {
00635 if (ORDER == Col)
00636 return (col * rows() + row);
00637 else
00638 return (row * cols() + col);
00639 } else {
00640 if (storeorder_ == Col)
00641 return (col * colstride() + row);
00642 else
00643 return (row * rowstride() + col);
00644 }
00645 }
00646
00647
00648
00649 protected:
00650 uint rows_;
00651 uint cols_;
00652
00653 private:
00654
00655
00656
00657 uint rowstride_;
00658 uint colstride_;
00659 matrix_order storeorder_;
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 };
00671
00672
00673
00791 template <typename T_type = double, matrix_order ORDER = Col,
00792 matrix_style STYLE = Concrete>
00793 class Matrix : public Matrix_base<ORDER, STYLE>,
00794 public DataBlockReference<T_type>
00795 {
00796 public:
00797
00798
00799
00800
00819 typedef matrix_random_access_iterator<T_type, ORDER, ORDER, STYLE>
00820 iterator;
00821
00840 typedef const_matrix_random_access_iterator<T_type, ORDER, ORDER,
00841 STYLE> const_iterator;
00842
00861 typedef typename
00862 std::reverse_iterator<matrix_random_access_iterator<T_type,
00863 ORDER, ORDER, STYLE> > reverse_iterator;
00864
00883 typedef typename
00884 std::reverse_iterator<const_matrix_random_access_iterator
00885 <T_type, ORDER, ORDER, STYLE> >
00886 const_reverse_iterator;
00887
00906 typedef matrix_forward_iterator<T_type, ORDER, ORDER, STYLE>
00907 forward_iterator;
00908
00928 typedef const_matrix_forward_iterator<T_type, ORDER, ORDER, STYLE>
00929 const_forward_iterator;
00930
00950 typedef matrix_bidirectional_iterator<T_type, ORDER, ORDER, STYLE>
00951 bidirectional_iterator;
00952
00972 typedef const_matrix_bidirectional_iterator<T_type, ORDER, ORDER,
00973 STYLE> const_bidirectional_iterator;
00974
00993 typedef typename
00994 std::reverse_iterator<matrix_bidirectional_iterator<T_type,
00995 ORDER, ORDER, STYLE> > reverse_bidirectional_iterator;
00996
01015 typedef typename
01016 std::reverse_iterator<const_matrix_bidirectional_iterator
01017 <T_type, ORDER, ORDER, STYLE> >
01018 const_reverse_bidirectional_iterator;
01019
01025 typedef T_type ttype;
01026
01027 private:
01028
01029 typedef DataBlockReference<T_type> DBRef;
01030 typedef Matrix_base<ORDER, STYLE> Base;
01031
01032 public:
01033
01034
01054 Matrix ()
01055 : Base (),
01056 DBRef ()
01057 {
01058 }
01059
01080 Matrix (T_type element)
01081 : Base (1, 1),
01082 DBRef (1)
01083 {
01084 data_[Base::index(0)] = element;
01085 }
01086
01114 Matrix (uint rows, uint cols, bool fill = true,
01115 T_type fill_value = 0)
01116 : Base (rows, cols),
01117 DBRef (rows * cols)
01118 {
01119
01120 if (fill)
01121 for (uint i = 0; i < Base::size(); ++i)
01122 data_[Base::index(i)] = fill_value;
01123 }
01124
01153 template <typename T_iterator>
01154 Matrix (uint rows, uint cols, T_iterator it)
01155 : Base (rows, cols),
01156 DBRef (rows * cols)
01157 {
01158
01159 for (uint i = 0; i < Base::size(); ++i) {
01160 data_[Base::index(i)] = *it;
01161 ++it;
01162 }
01163 }
01164
01194 Matrix (const std::string& path, bool oldstyle=false)
01195 : Base (),
01196 DBRef ()
01197 {
01198 std::ifstream file(path.c_str());
01199 SCYTHE_CHECK_10(! file, scythe_file_error,
01200 "Could not open file " << path);
01201
01202 if (oldstyle) {
01203 uint rows, cols;
01204 file >> rows >> cols;
01205 resize(rows, cols);
01206 std::copy(std::istream_iterator<T_type> (file),
01207 std::istream_iterator<T_type>(), begin_f<Row>());
01208 } else {
01209 std::string row;
01210
01211 unsigned int cols = -1;
01212 std::vector<std::vector<T_type> > vals;
01213 unsigned int rows = 0;
01214 while (std::getline(file, row)) {
01215 std::vector<T_type> column;
01216 std::istringstream rowstream(row);
01217 std::copy(std::istream_iterator<T_type> (rowstream),
01218 std::istream_iterator<T_type>(),
01219 std::back_inserter(column));
01220
01221 if (cols == -1)
01222 cols = (unsigned int) column.size();
01223
01224 SCYTHE_CHECK_10(cols != column.size(), scythe_file_error,
01225 "Row " << (rows + 1) << " of input file has "
01226 << column.size() << " elements, but should have " << cols);
01227
01228 vals.push_back(column);
01229 rows++;
01230 }
01231
01232 resize(rows, cols);
01233 for (unsigned int i = 0; i < rows; ++i)
01234 operator()(i, _) = Matrix<T_type>(1, cols, vals[i].begin());
01235 }
01236 }
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01274 Matrix (const Matrix& M)
01275 : Base (M),
01276 DBRef ()
01277 {
01278 if (STYLE == Concrete) {
01279 referenceNew(M.size());
01280 scythe::copy<ORDER,ORDER>(M, *this);
01281 } else
01282 referenceOther(M);
01283 }
01284
01320 template <matrix_order O, matrix_style S>
01321 Matrix (const Matrix<T_type, O, S> &M)
01322 : Base (M),
01323 DBRef ()
01324 {
01325 if (STYLE == Concrete) {
01326 referenceNew(M.size());
01327 scythe::copy<ORDER,ORDER> (M, *this);
01328 } else
01329 referenceOther(M);
01330 }
01331
01363 template <typename S_type, matrix_order O, matrix_style S>
01364 Matrix (const Matrix<S_type, O, S> &M)
01365 : Base(M),
01366 DBRef (M.size())
01367 {
01368 scythe::copy<ORDER,ORDER> (M, *this);
01369 }
01370
01411 template <matrix_order O, matrix_style S>
01412 Matrix (const Matrix<T_type, O, S> &M,
01413 uint x1, uint y1, uint x2, uint y2)
01414 : Base(M, x1, y1, x2, y2),
01415 DBRef(M, Base::index(x1, y1))
01416 {
01417
01418
01419
01420
01421
01422
01423
01424 if (STYLE == Concrete) {
01425 SCYTHE_THROW(scythe_style_error,
01426 "Tried to construct a concrete submatrix (Matrix)!");
01427 }
01428 }
01429
01430 public:
01431
01432
01435 ~Matrix() {}
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01470 template <matrix_order O, matrix_style S>
01471 inline void reference (const Matrix<T_type, O, S> &M)
01472 {
01473 if (STYLE == Concrete) {
01474 SCYTHE_THROW(scythe_style_error,
01475 "Concrete matrices cannot reference other matrices");
01476 } else {
01477 referenceOther(M);
01478 mimic(M);
01479 }
01480 }
01481
01500 inline Matrix<T_type, ORDER, Concrete> copy () const
01501 {
01502 Matrix<T_type, ORDER> res (Base::rows(), Base::cols(), false);
01503 std::copy(begin_f(), end_f(), res.begin_f());
01504
01505 return res;
01506 }
01507
01508
01509
01510
01511
01534 template <matrix_order O, matrix_style S>
01535 inline void copy (const Matrix<T_type, O, S>& M)
01536 {
01537 resize2Match(M);
01538 scythe::copy<ORDER,ORDER> (M, *this);
01539 }
01540
01541
01542
01560 inline T_type& operator[] (uint i)
01561 {
01562 SCYTHE_CHECK_30 (! Base::inRange(i), scythe_bounds_error,
01563 "Index " << i << " out of range");
01564
01565 return data_[Base::index(i)];
01566 }
01567
01585 inline T_type& operator[] (uint i) const
01586 {
01587 SCYTHE_CHECK_30 (! Base::inRange(i), scythe_bounds_error,
01588 "Index " << i << " out of range");
01589
01590 return data_[Base::index(i)];
01591 }
01592
01610 inline T_type& operator() (uint i)
01611 {
01612 SCYTHE_CHECK_30 (! Base::inRange(i), scythe_bounds_error,
01613 "Index " << i << " out of range");
01614
01615 return data_[Base::index(i)];
01616 }
01617
01635 inline T_type& operator() (uint i) const
01636 {
01637 SCYTHE_CHECK_30 (! Base::inRange(i), scythe_bounds_error,
01638 "Index " << i << " out of range");
01639
01640 return data_[Base::index(i)];
01641 }
01642
01661 inline T_type& operator() (uint i, uint j)
01662 {
01663 SCYTHE_CHECK_30 (! Base::inRange(i, j), scythe_bounds_error,
01664 "Index (" << i << ", " << j << ") out of range");
01665
01666 return data_[Base::index(i, j)];
01667 }
01668
01687 inline T_type& operator() (uint i, uint j) const
01688 {
01689 SCYTHE_CHECK_30 (! Base::inRange(i, j), scythe_bounds_error,
01690 "Index (" << i << ", " << j << ") out of range");
01691
01692 return data_[Base::index(i, j)];
01693 }
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01741 inline Matrix<T_type, ORDER, View>
01742 operator() (uint x1, uint y1, uint x2, uint y2)
01743 {
01744 SCYTHE_CHECK_20 (! Base::inRange(x1, y1)
01745 || ! Base::inRange(x2, y2)
01746 || x1 > x2 || y1 > y2,
01747 scythe_bounds_error,
01748 "Submatrix (" << x1 << ", " << y1 << ") ; ("
01749 << x2 << ", " << y2 << ") out of range or ill-formed");
01750
01751 return (Matrix<T_type, ORDER, View>(*this, x1, y1, x2, y2));
01752 }
01753
01773 inline Matrix<T_type, ORDER, View>
01774 operator() (uint x1, uint y1, uint x2, uint y2) const
01775 {
01776 SCYTHE_CHECK_20 (! Base::inRange(x1, y1)
01777 || ! Base::inRange(x2, y2)
01778 || x1 > x2 || y1 > y2,
01779 scythe_bounds_error,
01780 "Submatrix (" << x1 << ", " << y1 << ") ; ("
01781 << x2 << ", " << y2 << ") out of range or ill-formed");
01782
01783 return (Matrix<T_type, ORDER, View>(*this, x1, y1, x2, y2));
01784 }
01785
01804 inline Matrix<T_type, ORDER, View>
01805 operator() (const all_elements a, uint j)
01806 {
01807 SCYTHE_CHECK_20 (j >= Base::cols(), scythe_bounds_error,
01808 "Column vector index " << j << " out of range");
01809
01810 return (Matrix<T_type, ORDER, View>
01811 (*this, 0, j, Base::rows() - 1, j));
01812 }
01813
01829 inline Matrix<T_type, ORDER, View>
01830 operator() (const all_elements a, uint j) const
01831 {
01832 SCYTHE_CHECK_20 (j >= Base::cols(), scythe_bounds_error,
01833 "Column vector index " << j << " out of range");
01834
01835 return (Matrix<T_type, ORDER, View>
01836 (*this, 0, j, Base::rows() - 1, j));
01837 }
01838
01857 inline Matrix<T_type, ORDER, View>
01858 operator() (uint i, const all_elements b)
01859 {
01860 SCYTHE_CHECK_20 (i >= Base::rows(), scythe_bounds_error,
01861 "Row vector index " << i << " out of range");
01862
01863 return (Matrix<T_type, ORDER, View>
01864 (*this, i, 0, i, Base::cols() - 1));
01865 }
01866
01882 inline Matrix<T_type, ORDER, View>
01883 operator() (uint i, const all_elements b) const
01884 {
01885 SCYTHE_CHECK_20 (i >= Base::rows(), scythe_bounds_error,
01886 "Row vector index " << i << " out of range");
01887 return (Matrix<T_type, ORDER, View>
01888 (*this, i, 0, i, Base::cols() - 1));
01889 }
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01959 Matrix& operator= (const Matrix& M)
01960 {
01961 if (STYLE == Concrete) {
01962 resize2Match(M);
01963 scythe::copy<ORDER,ORDER> (M, *this);
01964 } else {
01965 #ifndef SCYTHE_VIEW_ASSIGNMENT_RECYCLE
01966 SCYTHE_CHECK_10 (Base::size() != M.size(),
01967 scythe_conformation_error,
01968 "LHS has dimensions (" << Base::rows()
01969 << ", " << Base::cols()
01970 << ") while RHS has dimensions (" << M.rows() << ", "
01971 << M.cols() << ")");
01972
01973 scythe::copy<ORDER,ORDER> (M, *this);
01974 #else
01975 copy_recycle<ORDER,ORDER>(M, *this);
01976 #endif
01977 }
01978
01979 return *this;
01980 }
01981
02032 template <matrix_order O, matrix_style S>
02033 Matrix &operator= (const Matrix<T_type, O, S> &M)
02034 {
02035 if (STYLE == Concrete) {
02036 resize2Match(M);
02037 scythe::copy<ORDER,ORDER> (M, *this);
02038 } else {
02039 #ifndef SCYTHE_VIEW_ASSIGNMENT_RECYCLE
02040 SCYTHE_CHECK_10 (Base::size() != M.size(),
02041 scythe_conformation_error,
02042 "LHS has dimensions (" << Base::rows()
02043 << ", " << Base::cols()
02044 << ") while RHS has dimensions (" << M.rows() << ", "
02045 << M.cols() << ")");
02046
02047 scythe::copy<ORDER,ORDER> (M, *this);
02048 #else
02049 copy_recycle<ORDER,ORDER>(M, *this);
02050 #endif
02051 }
02052
02053 return *this;
02054 }
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02103 ListInitializer<T_type, iterator, ORDER, STYLE>
02104 operator=(T_type x)
02105 {
02106 return (ListInitializer<T_type, iterator, ORDER, STYLE>
02107 (x, begin(),end(), this));
02108 }
02109
02137 template <typename ITERATOR, matrix_order O, matrix_style S>
02138 Matrix &operator=(ListInitializer<T_type, ITERATOR, O, S> li)
02139 {
02140 li.populate();
02141 *this = *(li.matrix_);
02142 return *this;
02143 }
02144
02145
02146
02147 private:
02148
02149
02150
02151
02152 template <typename OP, matrix_order O, matrix_style S>
02153 inline Matrix&
02154 elementWiseOperatorAssignment (const Matrix<T_type, O, S>& M,
02155 OP op)
02156 {
02157 SCYTHE_CHECK_10 (Base::size() != 1 && M.size() != 1 &&
02158 (Base::rows () != M.rows() || Base::cols() != M.cols()),
02159 scythe_conformation_error,
02160 "Matrices with dimensions (" << Base::rows()
02161 << ", " << Base::cols()
02162 << ") and (" << M.rows() << ", " << M.cols()
02163 << ") are not conformable");
02164
02165 if (Base::size() == 1) {
02166 T_type tmp = (*this)(0);
02167 resize2Match(M);
02168 std::transform(M.begin_f<ORDER>(), M.end_f<ORDER>(),
02169 begin_f(), std::bind1st(op, tmp));
02170 } else if (M.size() == 1) {
02171 std::transform(begin_f(), end_f(), begin_f(),
02172 std::bind2nd(op, M(0)));
02173 } else {
02174 std::transform(begin_f(), end_f(), M.begin_f<ORDER>(),
02175 begin_f(), op);
02176 }
02177
02178 return *this;
02179 }
02180
02181 public:
02201 template <matrix_order O, matrix_style S>
02202 inline Matrix& operator+= (const Matrix<T_type, O, S> &M)
02203 {
02204 return elementWiseOperatorAssignment(M, std::plus<T_type> ());
02205 }
02206
02223 inline Matrix& operator+= (T_type x)
02224 {
02225 return elementWiseOperatorAssignment(Matrix(x),
02226 std::plus<T_type> ());
02227 }
02228
02248 template <matrix_order O, matrix_style S>
02249 inline Matrix& operator-= (const Matrix<T_type, O, S> &M)
02250 {
02251 return elementWiseOperatorAssignment(M, std::minus<T_type> ());
02252 }
02253
02270 inline Matrix& operator-= (T_type x)
02271 {
02272 return elementWiseOperatorAssignment(Matrix(x),
02273 std::minus<T_type> ());
02274 }
02275
02300 template <matrix_order O, matrix_style S>
02301 inline Matrix& operator%= (const Matrix<T_type, O, S> &M)
02302 {
02303 return elementWiseOperatorAssignment(M,
02304 std::multiplies<T_type> ());
02305 }
02306
02323 inline Matrix& operator%= (T_type x)
02324 {
02325 return elementWiseOperatorAssignment(Matrix(x),
02326 std::multiplies<T_type> ());
02327 }
02328
02349 template <matrix_order O, matrix_style S>
02350 inline Matrix& operator/= (const Matrix<T_type, O, S> &M)
02351 {
02352 return elementWiseOperatorAssignment(M, std::divides<T_type>());
02353 }
02354
02371 inline Matrix& operator/= (T_type x)
02372 {
02373 return elementWiseOperatorAssignment(Matrix(x),
02374 std::divides<T_type> ());
02375 }
02376
02397 template <matrix_order O, matrix_style S>
02398 inline Matrix& operator^= (const Matrix<T_type, O, S> &M)
02399 {
02400 return elementWiseOperatorAssignment(M,
02401 exponentiate<T_type>());
02402 }
02403
02420 inline Matrix& operator^= (T_type x)
02421 {
02422 return elementWiseOperatorAssignment(Matrix(x),
02423 exponentiate<T_type> ());
02424 }
02425
02426
02427
02428
02429
02430
02461 template <matrix_order O, matrix_style S>
02462 Matrix& operator*= (const Matrix<T_type, O, S>& M)
02463 {
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474 Matrix<T_type, ORDER> res = (*this) * M;
02475 referenceOther(res);
02476 mimic(res);
02477
02478 return *this;
02479 }
02480
02504 inline Matrix& operator*= (T_type x)
02505 {
02506 return elementWiseOperatorAssignment(Matrix(x),
02507 std::multiplies<T_type> ());
02508 }
02509
02534 template <matrix_order O, matrix_style S> Matrix& kronecker
02535 (const Matrix<T_type, O, S>& M) { uint totalrows =
02536 Base::rows() * M.rows(); uint totalcols = Base::cols() *
02537 M.cols();
02538
02539 Matrix<T_type,ORDER> res(totalrows, totalcols, false);
02540
02541
02542
02543
02544
02545
02546 forward_iterator it = begin_f();
02547 if (ORDER == Row) {
02548 for (uint row = 0; row < totalrows; row += M.rows()) {
02549 for (uint col = 0; col < totalcols; col += M.cols()){
02550 res(row, col, row + M.rows() - 1, col + M.cols() - 1)
02551 = (*it) * M;
02552 it++;
02553 }
02554 }
02555 } else {
02556 for (uint col = 0; col < totalcols; col += M.cols()) {
02557 for (uint row = 0; row < totalrows; row += M.rows()){
02558 res(row, col, row + M.rows() - 1, col + M.cols() - 1)
02559 = (*it) * M;
02560 it++;
02561 }
02562 }
02563 }
02564
02565 referenceOther(res);
02566 mimic(res);
02567
02568 return *this;
02569 }
02570
02592 inline Matrix& kronecker (T_type x)
02593 {
02594 return elementWiseOperatorAssignment(Matrix(x),
02595 std::multiplies<T_type> ());
02596 }
02597
02598
02599
02619 template <matrix_order O, matrix_style S>
02620 inline Matrix& operator&= (const Matrix<T_type, O, S> &M)
02621 {
02622 return elementWiseOperatorAssignment(M,
02623 std::logical_and<T_type>());
02624 }
02625
02642 inline Matrix& operator&= (T_type x)
02643 {
02644 return elementWiseOperatorAssignment(Matrix(x),
02645 std::logical_and<T_type> ());
02646 }
02647
02667 template <matrix_order O, matrix_style S>
02668 inline Matrix& operator|= (const Matrix<T_type, O, S> &M)
02669 {
02670 return elementWiseOperatorAssignment(M,
02671 std::logical_or<T_type>());
02672 }
02673
02690 inline Matrix& operator|= (T_type x)
02691 {
02692 return elementWiseOperatorAssignment(Matrix(x),
02693 std::logical_or<T_type> ());
02694 }
02695
02696
02697
02698
02699
02700
02701
02702
02732 void resize (uint rows, uint cols, bool preserve=false)
02733 {
02734 if (preserve) {
02735
02736 Matrix<T_type, ORDER, View> tmp(*this);
02737 DBRef::referenceNew(rows * cols);
02738 Base::resize(rows, cols);
02739 uint min_cols = std::min(Base::cols(), tmp.cols());
02740 uint min_rows = std::min(Base::rows(), tmp.rows());
02741
02742
02743 if (ORDER == Col) {
02744 for (uint j = 0; j < min_cols; ++j)
02745 for (uint i = 0; i < min_rows; ++i)
02746 (*this)(i, j) = tmp(i, j);
02747 } else {
02748 for (uint i = 0; i < min_rows; ++i)
02749 for (uint j = 0; j < min_cols; ++j)
02750 (*this)(i, j) = tmp(i, j);
02751 }
02752 } else {
02753 DBRef::referenceNew(rows * cols);
02754 Base::resize(rows, cols);
02755 }
02756 }
02757
02773 template <typename T, matrix_order O, matrix_style S>
02774 inline void resize2Match(const Matrix<T, O, S> &M,
02775 bool preserve=false)
02776 {
02777 resize(M.rows(), M.cols(), preserve);
02778 }
02779
02780
02798 inline void detach ()
02799 {
02800 resize2Match(*this, true);
02801 }
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02834 inline void swap (Matrix &M)
02835 {
02836 Matrix tmp = *this;
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846 referenceOther(M);
02847 mimic(M);
02848
02849 M.referenceOther(tmp);
02850 M.mimic(tmp);
02851 }
02852
02853
02854
02855
02856
02857
02858
02859
02860
02869 inline bool isZero () const
02870 {
02871 const_forward_iterator last = end_f();
02872 return (last == std::find_if(begin_f(), last,
02873 std::bind1st(std::not_equal_to<T_type> (), 0)));
02874 }
02875
02876
02888 inline bool isDiagonal() const
02889 {
02890 if (! Base::isSquare())
02891 return false;
02892
02893
02894
02895
02896
02897 if (ORDER == Row) {
02898 for (uint i = 0; i < Base::rows(); ++i) {
02899 for (uint j = 0; j < Base::cols(); ++j) {
02900 if (i != j && (*this)(i, j) != 0)
02901 return false;
02902 }
02903 }
02904 } else {
02905 for (uint j = 0; j < Base::cols(); ++j) {
02906 for (uint i = 0; i < Base::rows(); ++i) {
02907 if (i != j && (*this)(i, j) != 0)
02908 return false;
02909 }
02910 }
02911 }
02912 return true;
02913 }
02914
02915
02927 inline bool isIdentity () const
02928 {
02929 if (! Base::isSquare())
02930 return false;
02931
02932 if (ORDER == Row) {
02933 for (uint i = 0; i < Base::rows(); ++i) {
02934 for (uint j = 0; j < Base::cols(); ++j) {
02935 if (i != j) {
02936 if ((*this)(i,j) != 0)
02937 return false;
02938 } else if ((*this)(i,j) != 1)
02939 return false;
02940 }
02941 }
02942 } else {
02943 for (uint j = 0; j < Base::rows(); ++j) {
02944 for (uint i = 0; i < Base::cols(); ++i) {
02945 if (i != j) {
02946 if ((*this)(i,j) != 0)
02947 return false;
02948 } else if ((*this)(i,j) != 1)
02949 return false;
02950 }
02951 }
02952 }
02953 return true;
02954 }
02955
02956
02966 inline bool isLowerTriangular () const
02967 {
02968
02969 if (ORDER == Row) {
02970 for (uint i = 0; i < Base::rows(); ++i)
02971 for (uint j = i + 1; j < Base::cols(); ++j)
02972 if ((*this)(i,j) != 0)
02973 return false;
02974 } else {
02975 for (uint j = 0; j < Base::cols(); ++j)
02976 for (uint i = 0; i < j; ++i)
02977 if ((*this)(i,j) != 0)
02978 return false;
02979 }
02980 return true;
02981 }
02982
02983
02993 inline bool isUpperTriangular () const
02994 {
02995
02996 if (ORDER == Row) {
02997 for (uint i = 0; i < Base::rows(); ++i)
02998 for (uint j = 0; j < i; ++j)
02999 if ((*this)(i,j) != 0)
03000 return false;
03001 } else {
03002 for (uint j = 0; j < Base::cols(); ++j)
03003 for (uint i = j + 1; i < Base::rows(); ++i)
03004 if ((*this)(i,j) != 0)
03005 return false;
03006 }
03007 return true;
03008 }
03009
03016 inline bool isSingular() const
03017 {
03018 if (! Base::isSquare() || Base::isNull())
03019 return false;
03020 if ((~(*this)) == (T_type) 0)
03021 return true;
03022 return false;
03023 }
03024
03025
03035 inline bool isSymmetric () const
03036 {
03037 if (! Base::isSquare())
03038 return false;
03039
03040 for (uint i = 1; i < Base::rows(); ++i)
03041 for (uint j = 0; j < i; ++j)
03042 if ((*this)(i, j) != (*this)(j, i))
03043 return false;
03044
03045 return true;
03046 }
03047
03048
03059 inline bool isSkewSymmetric () const
03060 {
03061 if (! Base::isSquare())
03062 return false;
03063
03064 for (uint i = 1; i < Base::rows(); ++i)
03065 for (uint j = 0; j < i; ++j)
03066 if ((*this)(i, j) != 0 - (*this)(j, i))
03067 return false;
03068
03069 return true;
03070 }
03071
03084 template <matrix_order O, matrix_style S>
03085 inline bool
03086 equals(const Matrix<T_type, O, S>& M) const
03087 {
03088 if (data_ == M.data_ && STYLE == Concrete && S == Concrete)
03089 return true;
03090 else if (data_ == M.data_ && Base::rows() == M.rows()
03091 && Base::cols() == M.cols()) {
03092 return true;
03093 } else if (this->isNull() && M.isNull())
03094 return true;
03095 else if (Base::rows() != M.rows() || Base::cols() != M.cols())
03096 return false;
03097
03098 return std::equal(begin_f(), end_f(),
03099 M.template begin_f<ORDER>());
03100 }
03101
03112 inline bool
03113 equals(T_type x) const
03114 {
03115 const_forward_iterator last = end_f();
03116 return (last == std::find_if(begin_f(), last,
03117 std::bind1st(std::not_equal_to<T_type> (), x)));
03118 }
03119
03120
03121
03122
03138 inline T_type* getArray () const
03139 {
03140 return data_;
03141 }
03142
03167 inline void
03168 save (const std::string& path, const char flag = 'n',
03169 const bool header = false)
03170 {
03171 std::ofstream out;
03172 if (flag == 'n') {
03173 std::fstream temp(path.c_str(), std::ios::in);
03174 if (! temp)
03175 out.open(path.c_str(), std::ios::out);
03176 else {
03177 temp.close();
03178 SCYTHE_THROW(scythe_file_error, "Cannot overwrite file "
03179 << path << " when flag = n");
03180 }
03181 } else if (flag == 'o')
03182 out.open(path.c_str(), std::ios::out | std::ios::trunc);
03183 else if (flag == 'a')
03184 out.open(path.c_str(), std::ios::out | std::ios::app);
03185 else
03186 SCYTHE_THROW(scythe_invalid_arg, "Invalid flag: " << flag);
03187
03188 if (! out)
03189 SCYTHE_THROW(scythe_file_error,
03190 "Could not open file " << path);
03191
03192 if (header) {
03193 out << Base::rows() << " " << Base::cols();
03194 for (uint i = 0; i < Base::size(); ++i)
03195 out << " " << (*this)[i];
03196 out << std::endl;
03197 } else {
03198 for (uint i = 0; i < Base::rows(); ++i) {
03199 for (uint j = 0; j < Base::cols(); ++j)
03200 out << (*this)(i,j) << " ";
03201 out << "\n";
03202 }
03203 }
03204 out.close();
03205 }
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03227 template <matrix_order I_ORDER>
03228 inline
03229 matrix_random_access_iterator<T_type, I_ORDER, ORDER, STYLE>
03230 begin ()
03231 {
03232 return matrix_random_access_iterator<T_type, I_ORDER, ORDER,
03233 STYLE>(*this);
03234 }
03235
03246 template <matrix_order I_ORDER>
03247 inline
03248 const_matrix_random_access_iterator<T_type, I_ORDER, ORDER, STYLE>
03249 begin() const
03250 {
03251 return const_matrix_random_access_iterator<T_type, I_ORDER,
03252 ORDER, STYLE>
03253 (*this);
03254 }
03255
03266 template <matrix_order I_ORDER>
03267 inline
03268 matrix_random_access_iterator<T_type, I_ORDER, ORDER, STYLE>
03269 end ()
03270 {
03271 return (begin<I_ORDER>() + Base::size());
03272 }
03273
03284 template <matrix_order I_ORDER>
03285 inline
03286 const_matrix_random_access_iterator<T_type, I_ORDER, ORDER, STYLE>
03287 end () const
03288 {
03289 return (begin<I_ORDER>() + Base::size());
03290 }
03291
03302 template <matrix_order I_ORDER>
03303 inline std::reverse_iterator<matrix_random_access_iterator<T_type,
03304 I_ORDER, ORDER, STYLE> >
03305 rbegin()
03306 {
03307 return std::reverse_iterator<matrix_random_access_iterator
03308 <T_type, I_ORDER, ORDER, STYLE> >
03309 (end<I_ORDER>());
03310 }
03311
03322 template <matrix_order I_ORDER>
03323 inline
03324 std::reverse_iterator<const_matrix_random_access_iterator
03325 <T_type, I_ORDER, ORDER, STYLE> >
03326 rbegin() const
03327 {
03328 return std::reverse_iterator<const_matrix_random_access_iterator
03329 <T_type, I_ORDER, ORDER, STYLE> >
03330 (end<I_ORDER>());
03331 }
03332
03344 template <matrix_order I_ORDER>
03345 inline std::reverse_iterator<matrix_random_access_iterator
03346 <T_type, I_ORDER, ORDER, STYLE> >
03347 rend()
03348 {
03349 return std::reverse_iterator<matrix_random_access_iterator
03350 <T_type, I_ORDER, ORDER, STYLE> >
03351 (begin<I_ORDER>());
03352 }
03353
03364 template <matrix_order I_ORDER>
03365 inline
03366 std::reverse_iterator<const_matrix_random_access_iterator
03367 <T_type, I_ORDER, ORDER, STYLE> >
03368 rend() const
03369 {
03370 return std::reverse_iterator<const_matrix_random_access_iterator
03371 <T_type, I_ORDER, ORDER, STYLE> >
03372 (begin<I_ORDER>());
03373 }
03374
03375
03376
03377
03378
03390 inline iterator begin ()
03391 {
03392 return iterator(*this);
03393 }
03394
03406 inline const_iterator begin() const
03407 {
03408 return const_iterator (*this);
03409 }
03410
03422 inline iterator end ()
03423 {
03424 return (begin() + Base::size());
03425 }
03426
03438 inline
03439 const_iterator end () const
03440 {
03441 return (begin() + Base::size());
03442 }
03443
03455 inline reverse_iterator rbegin()
03456 {
03457 return reverse_iterator (end());
03458 }
03459
03472 inline const_reverse_iterator rbegin() const
03473 {
03474 return const_reverse_iterator (end());
03475 }
03476
03489 inline reverse_iterator rend()
03490 {
03491 return reverse_iterator (begin());
03492 }
03493
03506 inline const_reverse_iterator rend() const
03507 {
03508 return const_reverse_iterator (begin());
03509 }
03510
03511
03512
03513
03514
03524 template <matrix_order I_ORDER>
03525 inline
03526 matrix_forward_iterator<T_type, I_ORDER, ORDER, STYLE>
03527 begin_f ()
03528 {
03529 return matrix_forward_iterator<T_type, I_ORDER, ORDER,
03530 STYLE>(*this);
03531 }
03532
03543 template <matrix_order I_ORDER>
03544 inline
03545 const_matrix_forward_iterator <T_type, I_ORDER, ORDER, STYLE>
03546 begin_f () const
03547 {
03548 return const_matrix_forward_iterator <T_type, I_ORDER,
03549 ORDER, STYLE>
03550 (*this);
03551 }
03552
03562 template <matrix_order I_ORDER>
03563 inline
03564 matrix_forward_iterator<T_type, I_ORDER, ORDER, STYLE>
03565 end_f ()
03566 {
03567 return (begin_f<I_ORDER>().set_end());
03568 }
03569
03580 template <matrix_order I_ORDER>
03581 inline
03582 const_matrix_forward_iterator<T_type, I_ORDER, ORDER, STYLE>
03583 end_f () const
03584 {
03585 return (begin_f<I_ORDER>().set_end());
03586 }
03587
03588
03589
03601 inline forward_iterator begin_f ()
03602 {
03603 return forward_iterator(*this);
03604 }
03605
03618 inline const_forward_iterator begin_f () const
03619 {
03620 return const_forward_iterator (*this);
03621 }
03622
03634 inline forward_iterator end_f ()
03635 {
03636 return (begin_f().set_end());
03637 }
03638
03651 inline
03652 const_forward_iterator end_f () const
03653 {
03654 return (begin_f().set_end());
03655 }
03656
03657
03658
03659
03660
03671 template <matrix_order I_ORDER>
03672 inline
03673 matrix_bidirectional_iterator<T_type, I_ORDER, ORDER, STYLE>
03674 begin_bd ()
03675 {
03676 return matrix_bidirectional_iterator<T_type, I_ORDER, ORDER,
03677 STYLE>(*this);
03678 }
03679
03690 template <matrix_order I_ORDER>
03691 inline
03692 const_matrix_bidirectional_iterator<T_type, I_ORDER, ORDER, STYLE>
03693 begin_bd () const
03694 {
03695 return const_matrix_bidirectional_iterator<T_type, I_ORDER,
03696 ORDER, STYLE>
03697 (*this);
03698 }
03699
03710 template <matrix_order I_ORDER>
03711 inline
03712 matrix_bidirectional_iterator<T_type, I_ORDER, ORDER, STYLE>
03713 end_bd ()
03714 {
03715 return (begin_bd<I_ORDER>().set_end());
03716 }
03717
03728 template <matrix_order I_ORDER>
03729 inline
03730 const_matrix_bidirectional_iterator<T_type, I_ORDER, ORDER, STYLE>
03731 end_bd () const
03732 {
03733 return (begin_bd<I_ORDER>.set_end());
03734 }
03735
03746 template <matrix_order I_ORDER>
03747 inline std::reverse_iterator<matrix_bidirectional_iterator<T_type,
03748 I_ORDER, ORDER, STYLE> >
03749 rbegin_bd ()
03750 {
03751 return std::reverse_iterator<matrix_bidirectional_iterator
03752 <T_type, I_ORDER, ORDER, STYLE> >
03753 (end_bd<I_ORDER>());
03754 }
03755
03766 template <matrix_order I_ORDER>
03767 inline
03768 std::reverse_iterator<const_matrix_bidirectional_iterator
03769 <T_type, I_ORDER, ORDER, STYLE> >
03770 rbegin_bd () const
03771 {
03772 return std::reverse_iterator<const_matrix_bidirectional_iterator
03773 <T_type, I_ORDER, ORDER, STYLE> >
03774 (end_bd<I_ORDER>());
03775 }
03776
03788 template <matrix_order I_ORDER>
03789 inline std::reverse_iterator<matrix_bidirectional_iterator
03790 <T_type, I_ORDER, ORDER, STYLE> >
03791 rend_bd ()
03792 {
03793 return std::reverse_iterator<matrix_bidirectional_iterator
03794 <T_type, I_ORDER, ORDER, STYLE> >
03795 (begin_bd<I_ORDER>());
03796 }
03797
03808 template <matrix_order I_ORDER>
03809 inline
03810 std::reverse_iterator<const_matrix_bidirectional_iterator
03811 <T_type, I_ORDER, ORDER, STYLE> >
03812 rend_bd () const
03813 {
03814 return std::reverse_iterator<const_matrix_bidirectional_iterator
03815 <T_type, I_ORDER, ORDER, STYLE> >
03816 (begin_bd<I_ORDER>());
03817 }
03818
03819
03820
03821
03822
03835 inline bidirectional_iterator begin_bd ()
03836 {
03837 return bidirectional_iterator(*this);
03838 }
03839
03852 inline const_bidirectional_iterator begin_bd() const
03853 {
03854 return const_bidirectional_iterator (*this);
03855 }
03856
03869 inline bidirectional_iterator end_bd ()
03870 {
03871 return (begin_bd().set_end());
03872 }
03873
03886 inline
03887 const_bidirectional_iterator end_bd () const
03888 {
03889 return (begin_bd().set_end());
03890 }
03891
03904 inline reverse_bidirectional_iterator rbegin_bd()
03905 {
03906 return reverse_bidirectional_iterator (end_bd());
03907 }
03908
03921 inline const_reverse_bidirectional_iterator rbegin_bd () const
03922 {
03923 return const_reverse_bidirectional_iterator (end_bd());
03924 }
03925
03938 inline reverse_bidirectional_iterator rend_bd ()
03939 {
03940 return reverse_bidirectional_iterator (begin_bd());
03941 }
03942
03955 inline const_reverse_iterator rend_bd () const
03956 {
03957 return const_reverse_bidirectiona_iterator (begin_bd());
03958 }
03959
03960 protected:
03961
03962
03963
03964
03965
03966
03967 using DBRef::data_;
03968 using Base::rows_;
03969 using Base::cols_;
03970
03971 };
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981
03982
03983
03984
03985
03986
03987
03988
03989
03990
03991
03992
03993
03994
03995
03996
03997
03998
03999
04000
04001
04002
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017
04018
04019
04020
04021
04022
04023
04024
04025
04026
04027
04028
04029
04030
04031
04032 #define SCYTHE_BINARY_OPERATOR_DMM(OP) \
04033 template <matrix_order ORDER, matrix_style L_STYLE, \
04034 matrix_order R_ORDER, matrix_style R_STYLE, \
04035 typename T_type> \
04036 inline Matrix<T_type, ORDER, Concrete> \
04037 OP (const Matrix<T_type, ORDER, L_STYLE>& lhs, \
04038 const Matrix<T_type, R_ORDER, R_STYLE>& rhs) \
04039 { \
04040 return OP <T_type, ORDER, Concrete>(lhs, rhs); \
04041 }
04042
04043 #define SCYTHE_BINARY_OPERATOR_GMS(OP) \
04044 template <typename T_type, matrix_order ORDER, matrix_style STYLE, \
04045 matrix_order L_ORDER, matrix_style L_STYLE> \
04046 inline Matrix<T_type, ORDER, STYLE> \
04047 OP (const Matrix<T_type, L_ORDER, L_STYLE>& lhs, \
04048 const typename Matrix<T_type>::ttype &rhs) \
04049 { \
04050 return (OP <T_type, ORDER, STYLE> \
04051 (lhs, Matrix<T_type, L_ORDER>(rhs))); \
04052 }
04053
04054 #define SCYTHE_BINARY_OPERATOR_DMS(OP) \
04055 template <matrix_order ORDER, matrix_style L_STYLE, \
04056 typename T_type> \
04057 inline Matrix<T_type, ORDER, Concrete> \
04058 OP (const Matrix<T_type, ORDER, L_STYLE>& lhs, \
04059 const typename Matrix<T_type>::ttype &rhs) \
04060 { \
04061 return (OP <T_type, ORDER, Concrete> (lhs, rhs)); \
04062 }
04063
04064 #define SCYTHE_BINARY_OPERATOR_GSM(OP) \
04065 template <typename T_type, matrix_order ORDER, matrix_style STYLE, \
04066 matrix_order R_ORDER, matrix_style R_STYLE> \
04067 inline Matrix<T_type, ORDER, STYLE> \
04068 OP (const typename Matrix<T_type>::ttype &lhs, \
04069 const Matrix<T_type, R_ORDER, R_STYLE>& rhs) \
04070 { \
04071 return (OP <T_type, ORDER, STYLE> \
04072 (Matrix<T_type, R_ORDER>(lhs), rhs)); \
04073 }
04074
04075 #define SCYTHE_BINARY_OPERATOR_DSM(OP) \
04076 template <matrix_order ORDER, matrix_style R_STYLE, \
04077 typename T_type> \
04078 inline Matrix<T_type, ORDER, Concrete> \
04079 OP (const typename Matrix<T_type>::ttype &lhs, \
04080 const Matrix<T_type, ORDER, R_STYLE>& rhs) \
04081 { \
04082 return (OP <T_type, ORDER, Concrete> (lhs, rhs)); \
04083 }
04084
04085 #define SCYTHE_BINARY_OPERATOR_DEFS(OP) \
04086 SCYTHE_BINARY_OPERATOR_DMM(OP) \
04087 SCYTHE_BINARY_OPERATOR_GMS(OP) \
04088 SCYTHE_BINARY_OPERATOR_DMS(OP) \
04089 SCYTHE_BINARY_OPERATOR_GSM(OP) \
04090 SCYTHE_BINARY_OPERATOR_DSM(OP)
04091
04092
04093
04094
04095
04096
04097
04098
04099
04100
04101
04102
04103
04104
04105
04153 template <typename T_type, matrix_order ORDER, matrix_style STYLE,
04154 matrix_order L_ORDER, matrix_style L_STYLE,
04155 matrix_order R_ORDER, matrix_style R_STYLE>
04156 inline Matrix<T_type, ORDER, STYLE>
04157 operator* (const Matrix<T_type, L_ORDER, L_STYLE>& lhs,
04158 const Matrix<T_type, R_ORDER, R_STYLE>& rhs)
04159 {
04160 if (lhs.size() == 1 || rhs.size() == 1)
04161 return (lhs % rhs);
04162
04163 SCYTHE_CHECK_10 (lhs.cols() != rhs.rows(),
04164 scythe_conformation_error,
04165 "Matrices with dimensions (" << lhs.rows()
04166 << ", " << lhs.cols()
04167 << ") and (" << rhs.rows() << ", " << rhs.cols()
04168 << ") are not multiplication-conformable");
04169
04170 Matrix<T_type, ORDER, Concrete> result (lhs.rows(), rhs.cols(), false);
04171
04172 T_type tmp;
04173 if (ORDER == Col) {
04174 for (uint j = 0; j < rhs.cols(); ++j) {
04175 for (uint i = 0; i < lhs.rows(); ++i)
04176 result(i, j) = (T_type) 0;
04177 for (uint l = 0; l < lhs.cols(); ++l) {
04178 tmp = rhs(l, j);
04179 for (uint i = 0; i < lhs.rows(); ++i)
04180 result(i, j) += tmp * lhs(i, l);
04181 }
04182 }
04183 } else {
04184 for (uint i = 0; i < lhs.rows(); ++i) {
04185 for (uint j = 0; j < rhs.cols(); ++j)
04186 result(i, j) = (T_type) 0;
04187 for (uint l = 0; l < rhs.rows(); ++l) {
04188 tmp = lhs(i, l);
04189 for (uint j = 0; j < rhs.cols(); ++j)
04190 result(i, j) += tmp * rhs(l,j);
04191 }
04192 }
04193 }
04194
04195 SCYTHE_VIEW_RETURN(T_type, ORDER, STYLE, result)
04196 }
04197
04198 SCYTHE_BINARY_OPERATOR_DEFS(operator*)
04199
04200
04225 template <typename T_type, matrix_order ORDER, matrix_style STYLE,
04226 matrix_order L_ORDER, matrix_style L_STYLE,
04227 matrix_order R_ORDER, matrix_style R_STYLE>
04228 inline Matrix<T_type, ORDER, STYLE>
04229 kronecker (const Matrix<T_type, L_ORDER, L_STYLE>& lhs,
04230 const Matrix<T_type, R_ORDER, R_STYLE>& rhs)
04231 {
04232 Matrix<T_type,ORDER,Concrete> res = lhs;
04233 res.kronecker(rhs);
04234 return (res);
04235 }
04236
04237 SCYTHE_BINARY_OPERATOR_DEFS(kronecker)
04238
04239
04240
04241
04242
04243 #define SCYTHE_GENERAL_BINARY_OPERATOR(OP,FUNCTOR) \
04244 template <typename T_type, matrix_order ORDER, matrix_style STYLE, \
04245 matrix_order L_ORDER, matrix_style L_STYLE, \
04246 matrix_order R_ORDER, matrix_style R_STYLE> \
04247 inline Matrix<T_type, ORDER, STYLE> \
04248 OP (const Matrix<T_type, L_ORDER, L_STYLE>& lhs, \
04249 const Matrix<T_type, R_ORDER, R_STYLE>& rhs) \
04250 { \
04251 SCYTHE_CHECK_10(lhs.size() != 1 && rhs.size() != 1 && \
04252 (lhs.rows() != rhs.rows() || lhs.cols() != rhs.cols()), \
04253 scythe_conformation_error, \
04254 "Matrices with dimensions (" << lhs.rows() \
04255 << ", " << lhs.cols() \
04256 << ") and (" << rhs.rows() << ", " << rhs.cols() \
04257 << ") are not conformable"); \
04258 \
04259 if (lhs.size() == 1) { \
04260 Matrix<T_type,ORDER,Concrete> res(rhs.rows(),rhs.cols(),false); \
04261 std::transform(rhs.begin_f(), rhs.end_f(), \
04262 res.template begin_f<R_ORDER>(), \
04263 std::bind1st(FUNCTOR <T_type>(), lhs(0))); \
04264 SCYTHE_VIEW_RETURN(T_type, ORDER, STYLE, res) \
04265 } \
04266 \
04267 Matrix<T_type,ORDER,Concrete> res(lhs.rows(), lhs.cols(), false); \
04268 \
04269 if (rhs.size() == 1) { \
04270 std::transform(lhs.begin_f(), lhs.end_f(), \
04271 res.template begin_f<L_ORDER> (), \
04272 std::bind2nd(FUNCTOR <T_type>(), rhs(0))); \
04273 } else { \
04274 std::transform(lhs.begin_f(), lhs.end_f(), \
04275 rhs.template begin_f<L_ORDER>(), \
04276 res.template begin_f<L_ORDER>(), \
04277 FUNCTOR <T_type> ()); \
04278 } \
04279 \
04280 SCYTHE_VIEW_RETURN(T_type, ORDER, STYLE, res) \
04281 }
04282
04283
04284
04315 SCYTHE_GENERAL_BINARY_OPERATOR (operator+, std::plus)
04316 SCYTHE_BINARY_OPERATOR_DEFS (operator+)
04317
04318
04319
04350 SCYTHE_GENERAL_BINARY_OPERATOR (operator-, std::minus)
04351 SCYTHE_BINARY_OPERATOR_DEFS (operator-)
04352
04353
04354
04386 SCYTHE_GENERAL_BINARY_OPERATOR (operator%, std::multiplies)
04387 SCYTHE_BINARY_OPERATOR_DEFS(operator%)
04388
04389
04390
04421 SCYTHE_GENERAL_BINARY_OPERATOR (operator/, std::divides)
04422 SCYTHE_BINARY_OPERATOR_DEFS (operator/)
04423
04424
04425
04456 SCYTHE_GENERAL_BINARY_OPERATOR (operator^, exponentiate)
04457 SCYTHE_BINARY_OPERATOR_DEFS (operator^)
04458
04459
04460
04461
04475 template <typename T_type, matrix_order R_ORDER, matrix_style R_STYLE,
04476 matrix_order ORDER, matrix_style STYLE>
04477 inline Matrix<T_type, R_ORDER, R_STYLE>
04478 operator- (const Matrix<T_type, ORDER, STYLE>& M)
04479 {
04480 Matrix<T_type, R_ORDER, Concrete> result(M.rows(), M.cols(), false);
04481 std::transform(M.template begin_f<ORDER>(),
04482 M.template end_f<ORDER>(),
04483 result.template begin_f<R_ORDER>(),
04484 std::negate<T_type> ());
04485 SCYTHE_VIEW_RETURN(T_type, R_ORDER, R_STYLE, result)
04486 }
04487
04488
04489 template <matrix_order ORDER, matrix_style P_STYLE, typename T_type>
04490 inline Matrix<T_type, ORDER, Concrete>
04491 operator- (const Matrix<T_type, ORDER, P_STYLE>& M)
04492 {
04493 return operator-<T_type, ORDER, Concrete> (M);
04494 }
04495
04496
04497
04513 template <matrix_order R_ORDER, matrix_style R_STYLE, typename T_type,
04514 matrix_order ORDER, matrix_style STYLE>
04515 inline Matrix<bool, R_ORDER, R_STYLE>
04516 operator! (const Matrix<T_type, ORDER, STYLE>& M)
04517 {
04518 Matrix<bool, R_ORDER, Concrete> result(M.rows(), M.cols(), false);
04519 std::transform(M.template begin_f<ORDER>(),
04520 M.template end_f<ORDER>(),
04521 result.template begin_f<R_ORDER>(),
04522 std::logical_not<T_type> ());
04523 SCYTHE_VIEW_RETURN(T_type, R_ORDER, R_STYLE, result)
04524 }
04525
04526
04527 template <typename T_type, matrix_order ORDER, matrix_style P_STYLE>
04528 inline Matrix<bool, ORDER, Concrete>
04529 operator! (const Matrix<T_type, ORDER, P_STYLE>& M)
04530 {
04531 return (operator!<ORDER, Concrete> (M));
04532 }
04533
04534
04535
04536
04537
04538
04539
04540 #define SCYTHE_GENERAL_BINARY_BOOL_OPERATOR(OP,FUNCTOR) \
04541 template <matrix_order ORDER, matrix_style STYLE, typename T_type, \
04542 matrix_order L_ORDER, matrix_style L_STYLE, \
04543 matrix_order R_ORDER, matrix_style R_STYLE> \
04544 inline Matrix<bool, ORDER, STYLE> \
04545 OP (const Matrix<T_type, L_ORDER, L_STYLE>& lhs, \
04546 const Matrix<T_type, R_ORDER, R_STYLE>& rhs) \
04547 { \
04548 SCYTHE_CHECK_10(lhs.size() != 1 && rhs.size() != 1 && \
04549 (lhs.rows() != rhs.rows() || lhs.cols() != rhs.cols()), \
04550 scythe_conformation_error, \
04551 "Matrices with dimensions (" << lhs.rows() \
04552 << ", " << lhs.cols() \
04553 << ") and (" << rhs.rows() << ", " << rhs.cols() \
04554 << ") are not conformable"); \
04555 \
04556 if (lhs.size() == 1) { \
04557 Matrix<bool,ORDER,Concrete> res(rhs.rows(),rhs.cols(),false); \
04558 std::transform(rhs.begin_f(), rhs.end_f(), \
04559 res.template begin_f<R_ORDER>(), \
04560 std::bind1st(FUNCTOR <T_type>(), lhs(0))); \
04561 SCYTHE_VIEW_RETURN(T_type, ORDER, STYLE, res) \
04562 } \
04563 \
04564 Matrix<bool,ORDER,Concrete> res(lhs.rows(), lhs.cols(), false); \
04565 \
04566 if (rhs.size() == 1) { \
04567 std::transform(lhs.begin_f(), lhs.end_f(), \
04568 res.template begin_f<L_ORDER> (), \
04569 std::bind2nd(FUNCTOR <T_type>(), rhs(0))); \
04570 } else { \
04571 std::transform(lhs.begin_f(), lhs.end_f(), \
04572 rhs.template begin_f<L_ORDER>(), \
04573 res.template begin_f<L_ORDER>(), \
04574 FUNCTOR <T_type> ()); \
04575 } \
04576 \
04577 SCYTHE_VIEW_RETURN(T_type, ORDER, STYLE, res) \
04578 }
04579
04580 #define SCYTHE_BINARY_BOOL_OPERATOR_DMM(OP) \
04581 template <typename T_type, matrix_order ORDER, matrix_style L_STYLE,\
04582 matrix_order R_ORDER, matrix_style R_STYLE> \
04583 inline Matrix<bool, ORDER, Concrete> \
04584 OP (const Matrix<T_type, ORDER, L_STYLE>& lhs, \
04585 const Matrix<T_type, R_ORDER, R_STYLE>& rhs) \
04586 { \
04587 return OP <ORDER, Concrete>(lhs, rhs); \
04588 }
04589
04590 #define SCYTHE_BINARY_BOOL_OPERATOR_GMS(OP) \
04591 template <matrix_order ORDER, matrix_style STYLE, typename T_type, \
04592 matrix_order L_ORDER, matrix_style L_STYLE> \
04593 inline Matrix<bool, ORDER, STYLE> \
04594 OP (const Matrix<T_type, L_ORDER, L_STYLE>& lhs, \
04595 const typename Matrix<T_type>::ttype &rhs) \
04596 { \
04597 return (OP <ORDER, STYLE> \
04598 (lhs, Matrix<T_type, L_ORDER>(rhs))); \
04599 }
04600
04601 #define SCYTHE_BINARY_BOOL_OPERATOR_DMS(OP) \
04602 template <typename T_type, matrix_order ORDER, matrix_style L_STYLE>\
04603 inline Matrix<bool, ORDER, Concrete> \
04604 OP (const Matrix<T_type, ORDER, L_STYLE>& lhs, \
04605 const typename Matrix<T_type>::ttype &rhs) \
04606 { \
04607 return (OP <ORDER, Concrete> (lhs, rhs)); \
04608 }
04609
04610 #define SCYTHE_BINARY_BOOL_OPERATOR_GSM(OP) \
04611 template <matrix_order ORDER, matrix_style STYLE, typename T_type, \
04612 matrix_order R_ORDER, matrix_style R_STYLE> \
04613 inline Matrix<bool, ORDER, STYLE> \
04614 OP (const typename Matrix<T_type>::ttype &lhs, \
04615 const Matrix<T_type, R_ORDER, R_STYLE>& rhs) \
04616 { \
04617 return (OP <ORDER, STYLE> \
04618 (Matrix<T_type, R_ORDER>(lhs), rhs)); \
04619 }
04620
04621 #define SCYTHE_BINARY_BOOL_OPERATOR_DSM(OP) \
04622 template <typename T_type, matrix_order ORDER, matrix_style R_STYLE>\
04623 inline Matrix<bool, ORDER, Concrete> \
04624 OP (const typename Matrix<T_type>::ttype &lhs, \
04625 const Matrix<T_type, ORDER, R_STYLE>& rhs) \
04626 { \
04627 return (OP <ORDER, Concrete> (lhs, rhs)); \
04628 }
04629
04630 #define SCYTHE_BINARY_BOOL_OPERATOR_DEFS(OP) \
04631 SCYTHE_BINARY_BOOL_OPERATOR_DMM(OP) \
04632 SCYTHE_BINARY_BOOL_OPERATOR_GMS(OP) \
04633 SCYTHE_BINARY_BOOL_OPERATOR_DMS(OP) \
04634 SCYTHE_BINARY_BOOL_OPERATOR_GSM(OP) \
04635 SCYTHE_BINARY_BOOL_OPERATOR_DSM(OP)
04636
04637
04638
04639
04640
04675 SCYTHE_GENERAL_BINARY_BOOL_OPERATOR (operator==, std::equal_to)
04676 SCYTHE_BINARY_BOOL_OPERATOR_DEFS (operator==)
04677
04712 SCYTHE_GENERAL_BINARY_BOOL_OPERATOR (operator!=, std::not_equal_to)
04713 SCYTHE_BINARY_BOOL_OPERATOR_DEFS (operator!=)
04714
04750 SCYTHE_GENERAL_BINARY_BOOL_OPERATOR (operator<, std::less)
04751 SCYTHE_BINARY_BOOL_OPERATOR_DEFS (operator<)
04752
04789 SCYTHE_GENERAL_BINARY_BOOL_OPERATOR (operator<=, std::less_equal)
04790 SCYTHE_BINARY_BOOL_OPERATOR_DEFS (operator<=)
04791
04827 SCYTHE_GENERAL_BINARY_BOOL_OPERATOR (operator>, std::greater)
04828 SCYTHE_BINARY_BOOL_OPERATOR_DEFS (operator>)
04829
04866 SCYTHE_GENERAL_BINARY_BOOL_OPERATOR (operator>=, std::greater_equal)
04867 SCYTHE_BINARY_BOOL_OPERATOR_DEFS (operator>=)
04868
04904 SCYTHE_GENERAL_BINARY_BOOL_OPERATOR (operator&, std::logical_and)
04905 SCYTHE_BINARY_BOOL_OPERATOR_DEFS (operator&)
04906
04907
04943 SCYTHE_GENERAL_BINARY_BOOL_OPERATOR (operator|, std::logical_or)
04944 SCYTHE_BINARY_BOOL_OPERATOR_DEFS (operator|)
04945
04946
04947
04948
04949
04950
04951
04952
04966 template <typename T, matrix_order O, matrix_style S>
04967 std::istream& operator>> (std::istream& is, Matrix<T,O,S>& M)
04968 {
04969 std::copy(std::istream_iterator<T> (is), std::istream_iterator<T>(),
04970 M.begin_f());
04971
04972 return is;
04973 }
04974
04975
04976
04977
04978
04993 template <typename T, matrix_order O, matrix_style S>
04994 std::ostream& operator<< (std::ostream& os, const Matrix<T,O,S>& M)
04995 {
04996
04997
04998
04999
05000
05001 std::ios_base::fmtflags preop = os.flags();
05002
05003 uint mlen = os.width();
05004 std::ostringstream oss;
05005 oss.precision(os.precision());
05006 oss << std::setiosflags(std::ios::fixed);
05007
05008 typename Matrix<T,O,S>::const_forward_iterator last = M.end_f();
05009 for (typename Matrix<T,O,S>::const_forward_iterator i = M.begin_f();
05010 i != last; ++i) {
05011 oss.str("");
05012 oss << (*i);
05013 if (oss.str().length() > mlen)
05014 mlen = oss.str().length();
05015 }
05016
05017
05018
05019
05020 os << std::setiosflags(std::ios::fixed);
05021
05022
05023 for (uint i = 0; i < M.rows(); ++i) {
05024 Matrix<T, O, View> row = M(i, _);
05025
05026
05027 typename Matrix<T,O,View>::const_forward_iterator row_last
05028 = row.end_f();
05029 for (typename
05030 Matrix<T,O,View>::forward_iterator el = row.begin_f();
05031 el != row_last; ++el) {
05032 os << std::setw(mlen) << *el << " ";
05033 }
05034 os << std::endl;
05035 }
05036
05037
05038
05039 os.flags(preop);
05040
05041 return os;
05042 }
05043
05044 #ifdef SCYTHE_LAPACK
05045
05046
05047
05048
05049
05050
05051
05052
05053
05054 template<>
05055 Matrix<>
05056 operator*<double,Col,Concrete,Col,Concrete>
05057 (const Matrix<>& lhs, const Matrix<>& rhs)
05058 {
05059 if (lhs.size() == 1 || rhs.size() == 1)
05060 return (lhs % rhs);
05061
05062 SCYTHE_DEBUG_MSG("Using lapack/blas for matrix multiplication");
05063 SCYTHE_CHECK_10 (lhs.cols() != rhs.rows(),
05064 scythe_conformation_error,
05065 "Matrices with dimensions (" << lhs.rows()
05066 << ", " << lhs.cols()
05067 << ") and (" << rhs.rows() << ", " << rhs.cols()
05068 << ") are not multiplication-conformable");
05069
05070 Matrix<> result (lhs.rows(), rhs.cols(), false);
05071
05072
05073 double* lhspnt = lhs.getArray();
05074 double* rhspnt = rhs.getArray();
05075 double* resultpnt = result.getArray();
05076 const double one(1.0);
05077 const double zero(0.0);
05078 int rows = (int) lhs.rows();
05079 int cols = (int) rhs.cols();
05080 int innerDim = (int) rhs.rows();
05081
05082
05083 lapack::dgemm_("N", "N", &rows, &cols, &innerDim, &one, lhspnt,
05084 &rows, rhspnt, &innerDim, &zero, resultpnt, &rows);
05085
05086 return result;
05087 }
05088 #endif
05089
05090 }
05091
05092 #endif