00001 00030 #ifndef MAT_H 00031 #define MAT_H 00032 00033 #ifndef _MSC_VER 00034 # include <itpp/config.h> 00035 #else 00036 # include <itpp/config_msvc.h> 00037 #endif 00038 00039 #include <itpp/base/itassert.h> 00040 #include <itpp/base/math/misc.h> 00041 #include <itpp/base/factory.h> 00042 00043 00044 namespace itpp 00045 { 00046 00047 // Declaration of Vec 00048 template<class Num_T> class Vec; 00049 // Declaration of Mat 00050 template<class Num_T> class Mat; 00051 // Declaration of bin 00052 class bin; 00053 00055 template<class Num_T> 00056 Mat<Num_T> concat_horizontal(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00058 template<class Num_T> 00059 Mat<Num_T> concat_vertical(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00060 00062 template<class Num_T> 00063 Mat<Num_T> operator+(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00065 template<class Num_T> 00066 Mat<Num_T> operator+(const Mat<Num_T> &m, Num_T t); 00068 template<class Num_T> 00069 Mat<Num_T> operator+(Num_T t, const Mat<Num_T> &m); 00070 00072 template<class Num_T> 00073 Mat<Num_T> operator-(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00075 template<class Num_T> 00076 Mat<Num_T> operator-(const Mat<Num_T> &m, Num_T t); 00078 template<class Num_T> 00079 Mat<Num_T> operator-(Num_T t, const Mat<Num_T> &m); 00081 template<class Num_T> 00082 Mat<Num_T> operator-(const Mat<Num_T> &m); 00083 00085 template<class Num_T> 00086 Mat<Num_T> operator*(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00088 template<class Num_T> 00089 Vec<Num_T> operator*(const Mat<Num_T> &m, const Vec<Num_T> &v); 00091 template<class Num_T> 00092 Mat<Num_T> operator*(const Vec<Num_T> &v, const Mat<Num_T> &m); 00094 template<class Num_T> 00095 Mat<Num_T> operator*(const Mat<Num_T> &m, Num_T t); 00097 template<class Num_T> 00098 Mat<Num_T> operator*(Num_T t, const Mat<Num_T> &m); 00099 00101 template<class Num_T> 00102 Mat<Num_T> elem_mult(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00104 template<class Num_T> 00105 void elem_mult_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2, 00106 Mat<Num_T> &out); 00108 template<class Num_T> 00109 void elem_mult_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2, 00110 const Mat<Num_T> &m3, Mat<Num_T> &out); 00112 template<class Num_T> 00113 void elem_mult_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2, 00114 const Mat<Num_T> &m3, const Mat<Num_T> &m4, 00115 Mat<Num_T> &out); 00117 template<class Num_T> 00118 void elem_mult_inplace(const Mat<Num_T> &m1, Mat<Num_T> &m2); 00120 template<class Num_T> 00121 Num_T elem_mult_sum(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00122 00124 template<class Num_T> 00125 Mat<Num_T> operator/(const Mat<Num_T> &m, Num_T t); 00126 00128 template<class Num_T> 00129 Mat<Num_T> elem_div(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00131 template<class Num_T> 00132 void elem_div_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2, 00133 Mat<Num_T> &out); 00135 template<class Num_T> 00136 Num_T elem_div_sum(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00137 00138 // ------------------------------------------------------------------------------------- 00139 // Declaration of Mat 00140 // ------------------------------------------------------------------------------------- 00141 00207 template<class Num_T> 00208 class Mat 00209 { 00210 public: 00212 typedef Num_T value_type; 00213 00215 explicit Mat(const Factory &f = DEFAULT_FACTORY); 00217 Mat(int rows, int cols, const Factory &f = DEFAULT_FACTORY); 00219 Mat(const Mat<Num_T> &m); 00221 Mat(const Mat<Num_T> &m, const Factory &f); 00223 Mat(const Vec<Num_T> &v, const Factory &f = DEFAULT_FACTORY); 00225 Mat(const std::string &str, const Factory &f = DEFAULT_FACTORY); 00227 Mat(const char *str, const Factory &f = DEFAULT_FACTORY); 00235 Mat(const Num_T *c_array, int rows, int cols, bool row_major = true, 00236 const Factory &f = DEFAULT_FACTORY); 00237 00239 ~Mat(); 00240 00242 int cols() const { return no_cols; } 00244 int rows() const { return no_rows; } 00246 int size() const { return datasize; } 00248 void set_size(int rows, int cols, bool copy = false); 00250 void zeros(); 00252 void clear() { zeros(); } 00254 void ones(); 00256 void set(const char *str); 00258 void set(const std::string &str); 00259 00261 const Num_T &operator()(int r, int c) const; 00263 Num_T &operator()(int r, int c); 00265 const Num_T &operator()(int i) const; 00267 Num_T &operator()(int i); 00269 const Num_T &get(int r, int c) const; 00271 void set(int r, int c, Num_T t); 00272 00278 Mat<Num_T> operator()(int r1, int r2, int c1, int c2) const; 00284 Mat<Num_T> get(int r1, int r2, int c1, int c2) const; 00285 00287 Vec<Num_T> get_row(int r) const; 00289 Mat<Num_T> get_rows(int r1, int r2) const; 00291 Mat<Num_T> get_rows(const Vec<int> &indexlist) const; 00293 Vec<Num_T> get_col(int c) const; 00295 Mat<Num_T> get_cols(int c1, int c2) const; 00297 Mat<Num_T> get_cols(const Vec<int> &indexlist) const; 00299 void set_row(int r, const Vec<Num_T> &v); 00301 void set_col(int c, const Vec<Num_T> &v); 00303 void set_rows(int r, const Mat<Num_T> &m); 00305 void set_cols(int c, const Mat<Num_T> &m); 00307 void copy_row(int to, int from); 00309 void copy_col(int to, int from); 00311 void swap_rows(int r1, int r2); 00313 void swap_cols(int c1, int c2); 00314 00316 void set_submatrix(int r1, int r2, int c1, int c2, const Mat<Num_T> &m); 00318 void set_submatrix(int r, int c, const Mat<Num_T> &m); 00320 void set_submatrix(int r1, int r2, int c1, int c2, Num_T t); 00321 00323 void del_row(int r); 00325 void del_rows(int r1, int r2); 00327 void del_col(int c); 00329 void del_cols(int c1, int c2); 00331 void ins_row(int r, const Vec<Num_T> &v); 00333 void ins_col(int c, const Vec<Num_T> &v); 00335 void append_row(const Vec<Num_T> &v); 00337 void append_col(const Vec<Num_T> &v); 00338 00340 Mat<Num_T> transpose() const; 00342 Mat<Num_T> T() const { return this->transpose(); } 00344 Mat<Num_T> hermitian_transpose() const; 00346 Mat<Num_T> H() const { return this->hermitian_transpose(); } 00347 00349 friend Mat<Num_T> concat_horizontal<>(const Mat<Num_T> &m1, 00350 const Mat<Num_T> &m2); 00352 friend Mat<Num_T> concat_vertical<>(const Mat<Num_T> &m1, 00353 const Mat<Num_T> &m2); 00354 00356 Mat<Num_T>& operator=(Num_T t); 00358 Mat<Num_T>& operator=(const Mat<Num_T> &m); 00360 Mat<Num_T>& operator=(const Vec<Num_T> &v); 00362 Mat<Num_T>& operator=(const char *str); 00363 00365 Mat<Num_T>& operator+=(const Mat<Num_T> &m); 00367 Mat<Num_T>& operator+=(Num_T t); 00369 friend Mat<Num_T> operator+<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00371 friend Mat<Num_T> operator+<>(const Mat<Num_T> &m, Num_T t); 00373 friend Mat<Num_T> operator+<>(Num_T t, const Mat<Num_T> &m); 00374 00376 Mat<Num_T>& operator-=(const Mat<Num_T> &m); 00378 Mat<Num_T>& operator-=(Num_T t); 00380 friend Mat<Num_T> operator-<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00382 friend Mat<Num_T> operator-<>(const Mat<Num_T> &m, Num_T t); 00384 friend Mat<Num_T> operator-<>(Num_T t, const Mat<Num_T> &m); 00386 friend Mat<Num_T> operator-<>(const Mat<Num_T> &m); 00387 00389 Mat<Num_T>& operator*=(const Mat<Num_T> &m); 00391 Mat<Num_T>& operator*=(Num_T t); 00393 friend Mat<Num_T> operator*<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00395 friend Vec<Num_T> operator*<>(const Mat<Num_T> &m, const Vec<Num_T> &v); 00407 friend Mat<Num_T> operator*<>(const Vec<Num_T> &v, const Mat<Num_T> &m); 00409 friend Mat<Num_T> operator*<>(const Mat<Num_T> &m, Num_T t); 00411 friend Mat<Num_T> operator*<>(Num_T t, const Mat<Num_T> &m); 00412 00414 friend Mat<Num_T> elem_mult<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00416 friend void elem_mult_out<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2, 00417 Mat<Num_T> &out); 00419 friend void elem_mult_out<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2, 00420 const Mat<Num_T> &m3, Mat<Num_T> &out); 00422 friend void elem_mult_out<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2, 00423 const Mat<Num_T> &m3, const Mat<Num_T> &m4, 00424 Mat<Num_T> &out); 00426 friend void elem_mult_inplace<>(const Mat<Num_T> &m1, Mat<Num_T> &m2); 00428 friend Num_T elem_mult_sum<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00429 00431 Mat<Num_T>& operator/=(Num_T t); 00433 friend Mat<Num_T> operator/<>(const Mat<Num_T> &m, Num_T t); 00435 Mat<Num_T>& operator/=(const Mat<Num_T> &m); 00436 00438 friend Mat<Num_T> elem_div<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00440 friend void elem_div_out<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2, 00441 Mat<Num_T> &out); 00443 friend Num_T elem_div_sum<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2); 00444 00446 bool operator==(const Mat<Num_T> &m) const; 00448 bool operator!=(const Mat<Num_T> &m) const; 00449 00451 Num_T &_elem(int r, int c) { return data[r+c*no_rows]; } 00453 const Num_T &_elem(int r, int c) const { return data[r+c*no_rows]; } 00455 Num_T &_elem(int i) { return data[i]; } 00457 const Num_T &_elem(int i) const { return data[i]; } 00458 00460 Num_T *_data() { return data; } 00462 const Num_T *_data() const { return data; } 00464 int _datasize() const { return datasize; } 00465 00466 protected: 00468 void alloc(int rows, int cols); 00470 void free(); 00471 00474 int datasize, no_rows, no_cols; 00476 00477 Num_T *data; 00479 const Factory &factory; 00480 00481 private: 00483 bool in_range(int r, int c) const { 00484 return ((r >= 0) && (r < no_rows) && (c >= 0) && (c < no_cols)); 00485 } 00487 bool row_in_range(int r) const { return ((r >= 0) && (r < no_rows)); } 00489 bool col_in_range(int c) const { return ((c >= 0) && (c < no_cols)); } 00491 bool in_range(int i) const { return ((i >= 0) && (i < datasize)); } 00492 }; 00493 00494 // ------------------------------------------------------------------------------------- 00495 // Type definitions of mat, cmat, imat, smat, and bmat 00496 // ------------------------------------------------------------------------------------- 00497 00502 typedef Mat<double> mat; 00503 00508 typedef Mat<std::complex<double> > cmat; 00509 00514 typedef Mat<int> imat; 00515 00520 typedef Mat<short int> smat; 00521 00528 typedef Mat<bin> bmat; 00529 00530 } //namespace itpp 00531 00532 00533 #include <itpp/base/vec.h> 00534 00535 namespace itpp 00536 { 00537 00538 // ---------------------------------------------------------------------- 00539 // Declaration of input and output streams for Mat 00540 // ---------------------------------------------------------------------- 00541 00546 template <class Num_T> 00547 std::ostream &operator<<(std::ostream &os, const Mat<Num_T> &m); 00548 00560 template <class Num_T> 00561 std::istream &operator>>(std::istream &is, Mat<Num_T> &m); 00562 00563 // ---------------------------------------------------------------------- 00564 // Implementation of templated Mat members and friends 00565 // ---------------------------------------------------------------------- 00566 00567 template<class Num_T> inline 00568 void Mat<Num_T>::alloc(int rows, int cols) 00569 { 00570 if ((rows > 0) && (cols > 0)) { 00571 datasize = rows * cols; 00572 no_rows = rows; 00573 no_cols = cols; 00574 create_elements(data, datasize, factory); 00575 } 00576 else { 00577 data = 0; 00578 datasize = 0; 00579 no_rows = 0; 00580 no_cols = 0; 00581 } 00582 } 00583 00584 template<class Num_T> inline 00585 void Mat<Num_T>::free() 00586 { 00587 destroy_elements(data, datasize); 00588 datasize = 0; 00589 no_rows = 0; 00590 no_cols = 0; 00591 } 00592 00593 00594 template<class Num_T> inline 00595 Mat<Num_T>::Mat(const Factory &f) : 00596 datasize(0), no_rows(0), no_cols(0), data(0), factory(f) {} 00597 00598 template<class Num_T> inline 00599 Mat<Num_T>::Mat(int rows, int cols, const Factory &f) : 00600 datasize(0), no_rows(0), no_cols(0), data(0), factory(f) 00601 { 00602 it_assert_debug((rows >= 0) && (cols >= 0), "Mat<>::Mat(): Wrong size"); 00603 alloc(rows, cols); 00604 } 00605 00606 template<class Num_T> inline 00607 Mat<Num_T>::Mat(const Mat<Num_T> &m) : 00608 datasize(0), no_rows(0), no_cols(0), data(0), factory(m.factory) 00609 { 00610 alloc(m.no_rows, m.no_cols); 00611 copy_vector(m.datasize, m.data, data); 00612 } 00613 00614 template<class Num_T> inline 00615 Mat<Num_T>::Mat(const Mat<Num_T> &m, const Factory &f) : 00616 datasize(0), no_rows(0), no_cols(0), data(0), factory(f) 00617 { 00618 alloc(m.no_rows, m.no_cols); 00619 copy_vector(m.datasize, m.data, data); 00620 } 00621 00622 template<class Num_T> inline 00623 Mat<Num_T>::Mat(const Vec<Num_T> &v, const Factory &f) : 00624 datasize(0), no_rows(0), no_cols(0), data(0), factory(f) 00625 { 00626 int size = v.size(); 00627 alloc(size, 1); 00628 copy_vector(size, v._data(), data); 00629 } 00630 00631 template<class Num_T> inline 00632 Mat<Num_T>::Mat(const std::string &str, const Factory &f) : 00633 datasize(0), no_rows(0), no_cols(0), data(0), factory(f) 00634 { 00635 set(str); 00636 } 00637 00638 template<class Num_T> inline 00639 Mat<Num_T>::Mat(const char *str, const Factory &f) : 00640 datasize(0), no_rows(0), no_cols(0), data(0), factory(f) 00641 { 00642 set(str); 00643 } 00644 00645 template<class Num_T> 00646 Mat<Num_T>::Mat(const Num_T *c_array, int rows, int cols, bool row_major, 00647 const Factory &f): 00648 datasize(0), no_rows(0), no_cols(0), data(0), factory(f) 00649 { 00650 alloc(rows, cols); 00651 if (!row_major) 00652 copy_vector(datasize, c_array, data); 00653 else 00654 for (int i = 0; i < rows; i++) 00655 for (int j = 0; j < cols; j++) 00656 data[i+j*no_rows] = c_array[i*no_cols+j]; 00657 } 00658 00659 template<class Num_T> inline 00660 Mat<Num_T>::~Mat() 00661 { 00662 free(); 00663 } 00664 00665 00666 template<class Num_T> 00667 void Mat<Num_T>::set_size(int rows, int cols, bool copy) 00668 { 00669 it_assert_debug((rows >= 0) && (cols >= 0), 00670 "Mat<>::set_size(): Wrong size"); 00671 // check if we have to resize the current matrix 00672 if ((no_rows == rows) && (no_cols == cols)) 00673 return; 00674 // check if one of dimensions is zero 00675 if ((rows == 0) || (cols == 0)) { 00676 free(); 00677 return; 00678 } 00679 // conditionally copy previous matrix content 00680 if (copy) { 00681 // create a temporary pointer to the allocated data 00682 Num_T* tmp = data; 00683 // store the current number of elements and number of rows 00684 int old_datasize = datasize; 00685 int old_rows = no_rows; 00686 // check the boundaries of the copied data 00687 int min_r = (no_rows < rows) ? no_rows : rows; 00688 int min_c = (no_cols < cols) ? no_cols : cols; 00689 // allocate new memory 00690 alloc(rows, cols); 00691 // copy the previous data into the allocated memory 00692 for (int i = 0; i < min_c; ++i) { 00693 copy_vector(min_r, &tmp[i*old_rows], &data[i*no_rows]); 00694 } 00695 // fill-in the rest of matrix with zeros 00696 for (int i = min_r; i < rows; ++i) 00697 for (int j = 0; j < cols; ++j) 00698 data[i+j*rows] = Num_T(0); 00699 for (int j = min_c; j < cols; ++j) 00700 for (int i = 0; i < min_r; ++i) 00701 data[i+j*rows] = Num_T(0); 00702 // delete old elements 00703 destroy_elements(tmp, old_datasize); 00704 } 00705 // if possible, reuse the allocated memory 00706 else if (datasize == rows * cols) { 00707 no_rows = rows; 00708 no_cols = cols; 00709 } 00710 // finally release old memory and allocate a new one 00711 else { 00712 free(); 00713 alloc(rows, cols); 00714 } 00715 } 00716 00717 template<class Num_T> inline 00718 void Mat<Num_T>::zeros() 00719 { 00720 for (int i = 0; i < datasize; i++) 00721 data[i] = Num_T(0); 00722 } 00723 00724 template<class Num_T> inline 00725 void Mat<Num_T>::ones() 00726 { 00727 for (int i = 0; i < datasize; i++) 00728 data[i] = Num_T(1); 00729 } 00730 00731 template<class Num_T> inline 00732 const Num_T& Mat<Num_T>::operator()(int r, int c) const 00733 { 00734 it_assert_debug(in_range(r, c), 00735 "Mat<>::operator(): Indexing out of range"); 00736 return data[r+c*no_rows]; 00737 } 00738 00739 template<class Num_T> inline 00740 Num_T& Mat<Num_T>::operator()(int r, int c) 00741 { 00742 it_assert_debug(in_range(r, c), 00743 "Mat<>::operator(): Indexing out of range"); 00744 return data[r+c*no_rows]; 00745 } 00746 00747 template<class Num_T> inline 00748 Num_T& Mat<Num_T>::operator()(int i) 00749 { 00750 it_assert_debug(in_range(i), "Mat<>::operator(): Index out of range"); 00751 return data[i]; 00752 } 00753 00754 template<class Num_T> inline 00755 const Num_T& Mat<Num_T>::operator()(int i) const 00756 { 00757 it_assert_debug(in_range(i), "Mat<>::operator(): Index out of range"); 00758 return data[i]; 00759 } 00760 00761 template<class Num_T> inline 00762 const Num_T& Mat<Num_T>::get(int r, int c) const 00763 { 00764 it_assert_debug(in_range(r, c), "Mat<>::get(): Indexing out of range"); 00765 return data[r+c*no_rows]; 00766 } 00767 00768 template<class Num_T> inline 00769 void Mat<Num_T>::set(int r, int c, Num_T t) 00770 { 00771 it_assert_debug(in_range(r, c), "Mat<>::set(): Indexing out of range"); 00772 data[r+c*no_rows] = t; 00773 } 00774 00775 00776 template<class Num_T> 00777 void Mat<Num_T>::set(const std::string &str) 00778 { 00779 // actual row counter 00780 int rows = 0; 00781 // number of rows to allocate next time (8, 16, 32, 64, etc.) 00782 int maxrows = 8; 00783 00784 // clean the current matrix content 00785 free(); 00786 00787 // variable to store the start of a current vector 00788 std::string::size_type beg = 0; 00789 std::string::size_type end = 0; 00790 while (end != std::string::npos) { 00791 // find next occurrence of a semicolon in string str 00792 end = str.find(';', beg); 00793 // parse first row into a vector v 00794 Vec<Num_T> v(str.substr(beg, end - beg)); 00795 int v_size = v.size(); 00796 00797 // this check is necessary to parse the following two strings as the 00798 // same matrix: "1 0 1; ; 1 1; " and "1 0 1; 0 0 0; 1 1 0" 00799 if ((end != std::string::npos) || (v_size > 0)) { 00800 // matrix empty -> insert v as a first row and allocate maxrows 00801 if (rows == 0) { 00802 set_size(maxrows, v_size, true); 00803 set_row(rows++, v); 00804 } 00805 else { 00806 // check if we need to resize the matrix 00807 if ((rows == maxrows) || (v_size != no_cols)) { 00808 // we need to add new rows 00809 if (rows == maxrows) { 00810 maxrows *= 2; 00811 } 00812 // check if we need to add new columns 00813 if (v_size > no_cols) { 00814 set_size(maxrows, v_size, true); 00815 } 00816 else { 00817 set_size(maxrows, no_cols, true); 00818 // set the size of the parsed vector to the number of columns 00819 v.set_size(no_cols, true); 00820 } 00821 } 00822 // set the parsed vector as the next row 00823 set_row(rows++, v); 00824 } 00825 } 00826 // update the starting position of the next vector in the parsed 00827 // string 00828 beg = end + 1; 00829 } // if ((end != std::string::npos) || (v.size > 0)) 00830 00831 set_size(rows, no_cols, true); 00832 } 00833 00834 template<class Num_T> 00835 void Mat<Num_T>::set(const char *str) 00836 { 00837 set(std::string(str)); 00838 } 00839 00840 template<class Num_T> inline 00841 Mat<Num_T> Mat<Num_T>::operator()(int r1, int r2, int c1, int c2) const 00842 { 00843 if (r1 == -1) r1 = no_rows - 1; 00844 if (r2 == -1) r2 = no_rows - 1; 00845 if (c1 == -1) c1 = no_cols - 1; 00846 if (c2 == -1) c2 = no_cols - 1; 00847 00848 it_assert_debug((r1 >= 0) && (r1 <= r2) && (r2 < no_rows) && 00849 (c1 >= 0) && (c1 <= c2) && (c2 < no_cols), 00850 "Mat<>::operator()(r1, r2, c1, c2): Wrong indexing"); 00851 00852 Mat<Num_T> s(r2 - r1 + 1, c2 - c1 + 1); 00853 00854 for (int i = 0;i < s.no_cols;i++) 00855 copy_vector(s.no_rows, data + r1 + (c1 + i)*no_rows, s.data + i*s.no_rows); 00856 00857 return s; 00858 } 00859 00860 template<class Num_T> inline 00861 Mat<Num_T> Mat<Num_T>::get(int r1, int r2, int c1, int c2) const 00862 { 00863 return (*this)(r1, r2, c1, c2); 00864 } 00865 00866 template<class Num_T> inline 00867 Vec<Num_T> Mat<Num_T>::get_row(int r) const 00868 { 00869 it_assert_debug(row_in_range(r), "Mat<>::get_row(): Index out of range"); 00870 Vec<Num_T> a(no_cols); 00871 00872 copy_vector(no_cols, data + r, no_rows, a._data(), 1); 00873 return a; 00874 } 00875 00876 template<class Num_T> 00877 Mat<Num_T> Mat<Num_T>::get_rows(int r1, int r2) const 00878 { 00879 it_assert_debug((r1 >= 0) && (r1 <= r2) && (r2 < no_rows), 00880 "Mat<>::get_rows(): Wrong indexing"); 00881 Mat<Num_T> m(r2 - r1 + 1, no_cols); 00882 00883 for (int i = 0; i < m.rows(); i++) 00884 copy_vector(no_cols, data + i + r1, no_rows, m.data + i, m.no_rows); 00885 00886 return m; 00887 } 00888 00889 template<class Num_T> 00890 Mat<Num_T> Mat<Num_T>::get_rows(const Vec<int> &indexlist) const 00891 { 00892 Mat<Num_T> m(indexlist.size(), no_cols); 00893 00894 for (int i = 0;i < indexlist.size();i++) { 00895 it_assert_debug(row_in_range(indexlist(i)), 00896 "Mat<>::get_rows(indexlist): Indexing out of range"); 00897 copy_vector(no_cols, data + indexlist(i), no_rows, m.data + i, m.no_rows); 00898 } 00899 00900 return m; 00901 } 00902 00903 template<class Num_T> inline 00904 Vec<Num_T> Mat<Num_T>::get_col(int c) const 00905 { 00906 it_assert_debug(col_in_range(c), "Mat<>::get_col(): Index out of range"); 00907 Vec<Num_T> a(no_rows); 00908 00909 copy_vector(no_rows, data + c*no_rows, a._data()); 00910 00911 return a; 00912 } 00913 00914 template<class Num_T> 00915 Mat<Num_T> Mat<Num_T>::get_cols(int c1, int c2) const 00916 { 00917 it_assert_debug((c1 >= 0) && (c1 <= c2) && (c2 < no_cols), 00918 "Mat<>::get_cols(): Wrong indexing"); 00919 Mat<Num_T> m(no_rows, c2 - c1 + 1); 00920 00921 for (int i = 0; i < m.cols(); i++) 00922 copy_vector(no_rows, data + (i + c1)*no_rows, m.data + i*m.no_rows); 00923 00924 return m; 00925 } 00926 00927 template<class Num_T> 00928 Mat<Num_T> Mat<Num_T>::get_cols(const Vec<int> &indexlist) const 00929 { 00930 Mat<Num_T> m(no_rows, indexlist.size()); 00931 00932 for (int i = 0; i < indexlist.size(); i++) { 00933 it_assert_debug(col_in_range(indexlist(i)), 00934 "Mat<>::get_cols(indexlist): Indexing out of range"); 00935 copy_vector(no_rows, data + indexlist(i)*no_rows, m.data + i*m.no_rows); 00936 } 00937 00938 return m; 00939 } 00940 00941 template<class Num_T> inline 00942 void Mat<Num_T>::set_row(int r, const Vec<Num_T> &v) 00943 { 00944 it_assert_debug(row_in_range(r), "Mat<>::set_row(): Index out of range"); 00945 it_assert_debug(v.size() == no_cols, 00946 "Mat<>::set_row(): Wrong size of input vector"); 00947 copy_vector(v.size(), v._data(), 1, data + r, no_rows); 00948 } 00949 00950 template<class Num_T> inline 00951 void Mat<Num_T>::set_col(int c, const Vec<Num_T> &v) 00952 { 00953 it_assert_debug(col_in_range(c), "Mat<>::set_col(): Index out of range"); 00954 it_assert_debug(v.size() == no_rows, 00955 "Mat<>::set_col(): Wrong size of input vector"); 00956 copy_vector(v.size(), v._data(), data + c*no_rows); 00957 } 00958 00959 00960 template<class Num_T> 00961 void Mat<Num_T>::set_rows(int r, const Mat<Num_T> &m) 00962 { 00963 it_assert_debug(row_in_range(r), "Mat<>::set_rows(): Index out of range"); 00964 it_assert_debug(no_cols == m.cols(), 00965 "Mat<>::set_rows(): Column sizes do not match"); 00966 it_assert_debug(m.rows() + r <= no_rows, 00967 "Mat<>::set_rows(): Not enough rows"); 00968 00969 for (int i = 0; i < m.rows(); ++i) { 00970 copy_vector(no_cols, m.data + i, m.no_rows, data + i + r, no_rows); 00971 } 00972 } 00973 00974 template<class Num_T> 00975 void Mat<Num_T>::set_cols(int c, const Mat<Num_T> &m) 00976 { 00977 it_assert_debug(col_in_range(c), "Mat<>::set_cols(): Index out of range"); 00978 it_assert_debug(no_rows == m.rows(), 00979 "Mat<>::set_cols(): Row sizes do not match"); 00980 it_assert_debug(m.cols() + c <= no_cols, 00981 "Mat<>::set_cols(): Not enough colums"); 00982 00983 for (int i = 0; i < m.cols(); ++i) { 00984 copy_vector(no_rows, m.data + i*no_rows, data + (i + c)*no_rows); 00985 } 00986 } 00987 00988 00989 template<class Num_T> inline 00990 void Mat<Num_T>::copy_row(int to, int from) 00991 { 00992 it_assert_debug(row_in_range(to) && row_in_range(from), 00993 "Mat<>::copy_row(): Indexing out of range"); 00994 if (from == to) 00995 return; 00996 00997 copy_vector(no_cols, data + from, no_rows, data + to, no_rows); 00998 } 00999 01000 template<class Num_T> inline 01001 void Mat<Num_T>::copy_col(int to, int from) 01002 { 01003 it_assert_debug(col_in_range(to) && col_in_range(from), 01004 "Mat<>::copy_col(): Indexing out of range"); 01005 if (from == to) 01006 return; 01007 01008 copy_vector(no_rows, data + from*no_rows, data + to*no_rows); 01009 } 01010 01011 template<class Num_T> inline 01012 void Mat<Num_T>::swap_rows(int r1, int r2) 01013 { 01014 it_assert_debug(row_in_range(r1) && row_in_range(r2), 01015 "Mat<>::swap_rows(): Indexing out of range"); 01016 if (r1 == r2) 01017 return; 01018 01019 swap_vector(no_cols, data + r1, no_rows, data + r2, no_rows); 01020 } 01021 01022 template<class Num_T> inline 01023 void Mat<Num_T>::swap_cols(int c1, int c2) 01024 { 01025 it_assert_debug(col_in_range(c1) && col_in_range(c2), 01026 "Mat<>::swap_cols(): Indexing out of range"); 01027 if (c1 == c2) 01028 return; 01029 01030 swap_vector(no_rows, data + c1*no_rows, data + c2*no_rows); 01031 } 01032 01033 template<class Num_T> 01034 void Mat<Num_T>::set_submatrix(int r1, int r2, int c1, int c2, 01035 const Mat<Num_T> &m) 01036 { 01037 01038 if (r1 == -1) r1 = no_rows - 1; 01039 if (r2 == -1) r2 = no_rows - 1; 01040 if (c1 == -1) c1 = no_cols - 1; 01041 if (c2 == -1) c2 = no_cols - 1; 01042 01043 it_assert_debug(r1 >= 0 && r2 >= 0 && r1 < no_rows && r2 < no_rows && 01044 c1 >= 0 && c2 >= 0 && c1 < no_cols && c2 < no_cols, "Mat<Num_T>::set_submatrix(): index out of range"); 01045 01046 it_assert_debug(r2 >= r1 && c2 >= c1, "Mat<Num_T>::set_submatrix: r2<r1 or c2<c1"); 01047 it_assert_debug(m.no_rows == r2 - r1 + 1 && m.no_cols == c2 - c1 + 1, "Mat<Num_T>::set_submatrix(): sizes don't match"); 01048 01049 for (int i = 0; i < m.no_cols; i++) 01050 copy_vector(m.no_rows, m.data + i*m.no_rows, data + (c1 + i)*no_rows + r1); 01051 } 01052 01053 01054 01055 template<class Num_T> inline 01056 void Mat<Num_T>::set_submatrix(int r, int c, const Mat<Num_T> &m) 01057 { 01058 it_assert_debug((r >= 0) && (r + m.no_rows <= no_rows) && 01059 (c >= 0) && (c + m.no_cols <= no_cols), 01060 "Mat<>::set_submatrix(): Indexing out of range " 01061 "or wrong input matrix"); 01062 for (int i = 0; i < m.no_cols; i++) 01063 copy_vector(m.no_rows, m.data + i*m.no_rows, data + (c + i)*no_rows + r); 01064 } 01065 01066 01067 01068 template<class Num_T> inline 01069 void Mat<Num_T>::set_submatrix(int r1, int r2, int c1, int c2, Num_T t) 01070 { 01071 01072 if (r1 == -1) r1 = no_rows - 1; 01073 if (r2 == -1) r2 = no_rows - 1; 01074 if (c1 == -1) c1 = no_cols - 1; 01075 if (c2 == -1) c2 = no_cols - 1; 01076 it_assert_debug((r1 >= 0) && (r1 <= r2) && (r2 < no_rows) && 01077 (c1 >= 0) && (c1 <= c2) && (c2 < no_cols), 01078 "Mat<>::set_submatrix(): Wrong indexing"); 01079 01080 int i, j, pos, rows = r2 - r1 + 1; 01081 01082 for (i = c1; i <= c2; i++) { 01083 pos = i * no_rows + r1; 01084 for (j = 0; j < rows; j++) { 01085 data[pos++] = t; 01086 } 01087 } 01088 } 01089 01090 template<class Num_T> 01091 void Mat<Num_T>::del_row(int r) 01092 { 01093 it_assert_debug(row_in_range(r), "Mat<>::del_row(): Index out of range"); 01094 Mat<Num_T> Temp(*this); 01095 set_size(no_rows - 1, no_cols, false); 01096 for (int i = 0 ; i < r ; i++) { 01097 copy_vector(no_cols, &Temp.data[i], no_rows + 1, &data[i], no_rows); 01098 } 01099 for (int i = r ; i < no_rows ; i++) { 01100 copy_vector(no_cols, &Temp.data[i+1], no_rows + 1, &data[i], no_rows); 01101 } 01102 01103 } 01104 01105 template<class Num_T> 01106 void Mat<Num_T>::del_rows(int r1, int r2) 01107 { 01108 it_assert_debug((r1 >= 0) && (r1 <= r2) && (r2 < no_rows), 01109 "Mat<>::del_rows(): Indexing out of range"); 01110 Mat<Num_T> Temp(*this); 01111 int no_del_rows = r2 - r1 + 1; 01112 set_size(no_rows - no_del_rows, no_cols, false); 01113 for (int i = 0; i < r1 ; ++i) { 01114 copy_vector(no_cols, &Temp.data[i], Temp.no_rows, &data[i], no_rows); 01115 } 01116 for (int i = r2 + 1; i < Temp.no_rows; ++i) { 01117 copy_vector(no_cols, &Temp.data[i], Temp.no_rows, &data[i-no_del_rows], 01118 no_rows); 01119 } 01120 } 01121 01122 template<class Num_T> 01123 void Mat<Num_T>::del_col(int c) 01124 { 01125 it_assert_debug(col_in_range(c), "Mat<>::del_col(): Index out of range"); 01126 Mat<Num_T> Temp(*this); 01127 01128 set_size(no_rows, no_cols - 1, false); 01129 copy_vector(c*no_rows, Temp.data, data); 01130 copy_vector((no_cols - c)*no_rows, &Temp.data[(c+1)*no_rows], &data[c*no_rows]); 01131 } 01132 01133 template<class Num_T> 01134 void Mat<Num_T>::del_cols(int c1, int c2) 01135 { 01136 it_assert_debug((c1 >= 0) && (c1 <= c2) && (c2 < no_cols), 01137 "Mat<>::del_cols(): Indexing out of range"); 01138 Mat<Num_T> Temp(*this); 01139 int n_deleted_cols = c2 - c1 + 1; 01140 set_size(no_rows, no_cols - n_deleted_cols, false); 01141 copy_vector(c1*no_rows, Temp.data, data); 01142 copy_vector((no_cols - c1)*no_rows, &Temp.data[(c2+1)*no_rows], &data[c1*no_rows]); 01143 } 01144 01145 template<class Num_T> 01146 void Mat<Num_T>::ins_row(int r, const Vec<Num_T> &v) 01147 { 01148 it_assert_debug((r >= 0) && (r <= no_rows), 01149 "Mat<>::ins_row(): Index out of range"); 01150 it_assert_debug((v.size() == no_cols) || (no_rows == 0), 01151 "Mat<>::ins_row(): Wrong size of the input vector"); 01152 01153 if (no_cols == 0) { 01154 no_cols = v.size(); 01155 } 01156 01157 Mat<Num_T> Temp(*this); 01158 set_size(no_rows + 1, no_cols, false); 01159 01160 for (int i = 0 ; i < r ; i++) { 01161 copy_vector(no_cols, &Temp.data[i], no_rows - 1, &data[i], no_rows); 01162 } 01163 copy_vector(no_cols, v._data(), 1, &data[r], no_rows); 01164 for (int i = r + 1 ; i < no_rows ; i++) { 01165 copy_vector(no_cols, &Temp.data[i-1], no_rows - 1, &data[i], no_rows); 01166 } 01167 } 01168 01169 template<class Num_T> 01170 void Mat<Num_T>::ins_col(int c, const Vec<Num_T> &v) 01171 { 01172 it_assert_debug((c >= 0) && (c <= no_cols), 01173 "Mat<>::ins_col(): Index out of range"); 01174 it_assert_debug((v.size() == no_rows) || (no_cols == 0), 01175 "Mat<>::ins_col(): Wrong size of the input vector"); 01176 01177 if (no_rows == 0) { 01178 no_rows = v.size(); 01179 } 01180 01181 Mat<Num_T> Temp(*this); 01182 set_size(no_rows, no_cols + 1, false); 01183 01184 copy_vector(c*no_rows, Temp.data, data); 01185 copy_vector(no_rows, v._data(), &data[c*no_rows]); 01186 copy_vector((no_cols - c - 1)*no_rows, &Temp.data[c*no_rows], &data[(c+1)*no_rows]); 01187 } 01188 01189 template<class Num_T> inline 01190 void Mat<Num_T>::append_row(const Vec<Num_T> &v) 01191 { 01192 ins_row(no_rows, v); 01193 } 01194 01195 template<class Num_T> inline 01196 void Mat<Num_T>::append_col(const Vec<Num_T> &v) 01197 { 01198 ins_col(no_cols, v); 01199 } 01200 01201 template<class Num_T> 01202 Mat<Num_T> Mat<Num_T>::transpose() const 01203 { 01204 Mat<Num_T> temp(no_cols, no_rows); 01205 for (int i = 0; i < no_rows; ++i) { 01206 copy_vector(no_cols, &data[i], no_rows, &temp.data[i * no_cols], 1); 01207 } 01208 return temp; 01209 } 01210 01212 template<> 01213 cmat cmat::hermitian_transpose() const; 01215 01216 template<class Num_T> 01217 Mat<Num_T> Mat<Num_T>::hermitian_transpose() const 01218 { 01219 Mat<Num_T> temp(no_cols, no_rows); 01220 for (int i = 0; i < no_rows; ++i) { 01221 copy_vector(no_cols, &data[i], no_rows, &temp.data[i * no_cols], 1); 01222 } 01223 return temp; 01224 } 01225 01226 template<class Num_T> 01227 Mat<Num_T> concat_horizontal(const Mat<Num_T> &m1, const Mat<Num_T> &m2) 01228 { 01229 // if one of the input matrix is empty just copy the other one as a result 01230 if (m1.no_cols == 0) 01231 return m2; 01232 if (m2.no_cols == 0) 01233 return m1; 01234 it_assert_debug(m1.no_rows == m2.no_rows, 01235 "Mat<>::concat_horizontal(): Wrong sizes"); 01236 int no_rows = m1.no_rows; 01237 Mat<Num_T> temp(no_rows, m1.no_cols + m2.no_cols); 01238 for (int i = 0; i < m1.no_cols; ++i) { 01239 copy_vector(no_rows, &m1.data[i * no_rows], &temp.data[i * no_rows]); 01240 } 01241 for (int i = 0; i < m2.no_cols; ++i) { 01242 copy_vector(no_rows, &m2.data[i * no_rows], &temp.data[(m1.no_cols + i) 01243 * no_rows]); 01244 } 01245 return temp; 01246 } 01247 01248 template<class Num_T> 01249 Mat<Num_T> concat_vertical(const Mat<Num_T> &m1, const Mat<Num_T> &m2) 01250 { 01251 // if one of the input matrix is empty just copy the other one as a result 01252 if (m1.no_rows == 0) 01253 return m2; 01254 if (m2.no_rows == 0) 01255 return m1; 01256 it_assert_debug(m1.no_cols == m2.no_cols, 01257 "Mat<>::concat_vertical(): Wrong sizes"); 01258 int no_cols = m1.no_cols; 01259 Mat<Num_T> temp(m1.no_rows + m2.no_rows, no_cols); 01260 for (int i = 0; i < no_cols; ++i) { 01261 copy_vector(m1.no_rows, &m1.data[i * m1.no_rows], 01262 &temp.data[i * temp.no_rows]); 01263 copy_vector(m2.no_rows, &m2.data[i * m2.no_rows], 01264 &temp.data[i * temp.no_rows + m1.no_rows]); 01265 } 01266 return temp; 01267 } 01268 01269 template<class Num_T> inline 01270 Mat<Num_T>& Mat<Num_T>::operator=(Num_T t) 01271 { 01272 for (int i = 0; i < datasize; i++) 01273 data[i] = t; 01274 return *this; 01275 } 01276 01277 template<class Num_T> inline 01278 Mat<Num_T>& Mat<Num_T>::operator=(const Mat<Num_T> &m) 01279 { 01280 if (this != &m) { 01281 set_size(m.no_rows, m.no_cols, false); 01282 if (m.datasize != 0) 01283 copy_vector(m.datasize, m.data, data); 01284 } 01285 return *this; 01286 } 01287 01288 template<class Num_T> inline 01289 Mat<Num_T>& Mat<Num_T>::operator=(const Vec<Num_T> &v) 01290 { 01291 it_assert_debug(((no_rows == 1) && (no_cols == v.size())) 01292 || ((no_cols == 1) && (no_rows == v.size())), 01293 "Mat<>::operator=(): Wrong size of the input vector"); 01294 set_size(v.size(), 1, false); 01295 copy_vector(v.size(), v._data(), data); 01296 return *this; 01297 } 01298 01299 template<class Num_T> inline 01300 Mat<Num_T>& Mat<Num_T>::operator=(const char *str) 01301 { 01302 set(str); 01303 return *this; 01304 } 01305 01306 //-------------------- Templated friend functions -------------------------- 01307 01308 template<class Num_T> 01309 Mat<Num_T>& Mat<Num_T>::operator+=(const Mat<Num_T> &m) 01310 { 01311 if (datasize == 0) 01312 operator=(m); 01313 else { 01314 int i, j, m_pos = 0, pos = 0; 01315 it_assert_debug(m.no_rows == no_rows && m.no_cols == no_cols, "Mat<Num_T>::operator+=: wrong sizes"); 01316 for (i = 0; i < no_cols; i++) { 01317 for (j = 0; j < no_rows; j++) 01318 data[pos+j] += m.data[m_pos+j]; 01319 pos += no_rows; 01320 m_pos += m.no_rows; 01321 } 01322 } 01323 return *this; 01324 } 01325 01326 template<class Num_T> inline 01327 Mat<Num_T>& Mat<Num_T>::operator+=(Num_T t) 01328 { 01329 for (int i = 0; i < datasize; i++) 01330 data[i] += t; 01331 return *this; 01332 } 01333 01334 template<class Num_T> 01335 Mat<Num_T> operator+(const Mat<Num_T> &m1, const Mat<Num_T> &m2) 01336 { 01337 Mat<Num_T> r(m1.no_rows, m1.no_cols); 01338 int i, j, m1_pos = 0, m2_pos = 0, r_pos = 0; 01339 01340 it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols), 01341 "Mat<>::operator+(): Wrong sizes"); 01342 01343 for (i = 0; i < r.no_cols; i++) { 01344 for (j = 0; j < r.no_rows; j++) 01345 r.data[r_pos+j] = m1.data[m1_pos+j] + m2.data[m2_pos+j]; 01346 // next column 01347 m1_pos += m1.no_rows; 01348 m2_pos += m2.no_rows; 01349 r_pos += r.no_rows; 01350 } 01351 01352 return r; 01353 } 01354 01355 01356 template<class Num_T> 01357 Mat<Num_T> operator+(const Mat<Num_T> &m, Num_T t) 01358 { 01359 Mat<Num_T> r(m.no_rows, m.no_cols); 01360 01361 for (int i = 0; i < r.datasize; i++) 01362 r.data[i] = m.data[i] + t; 01363 01364 return r; 01365 } 01366 01367 template<class Num_T> 01368 Mat<Num_T> operator+(Num_T t, const Mat<Num_T> &m) 01369 { 01370 Mat<Num_T> r(m.no_rows, m.no_cols); 01371 01372 for (int i = 0; i < r.datasize; i++) 01373 r.data[i] = t + m.data[i]; 01374 01375 return r; 01376 } 01377 01378 template<class Num_T> 01379 Mat<Num_T>& Mat<Num_T>::operator-=(const Mat<Num_T> &m) 01380 { 01381 int i, j, m_pos = 0, pos = 0; 01382 01383 if (datasize == 0) { 01384 set_size(m.no_rows, m.no_cols, false); 01385 for (i = 0; i < no_cols; i++) { 01386 for (j = 0; j < no_rows; j++) 01387 data[pos+j] = -m.data[m_pos+j]; 01388 // next column 01389 m_pos += m.no_rows; 01390 pos += no_rows; 01391 } 01392 } 01393 else { 01394 it_assert_debug((m.no_rows == no_rows) && (m.no_cols == no_cols), 01395 "Mat<>::operator-=(): Wrong sizes"); 01396 for (i = 0; i < no_cols; i++) { 01397 for (j = 0; j < no_rows; j++) 01398 data[pos+j] -= m.data[m_pos+j]; 01399 // next column 01400 m_pos += m.no_rows; 01401 pos += no_rows; 01402 } 01403 } 01404 return *this; 01405 } 01406 01407 template<class Num_T> 01408 Mat<Num_T> operator-(const Mat<Num_T> &m1, const Mat<Num_T> &m2) 01409 { 01410 Mat<Num_T> r(m1.no_rows, m1.no_cols); 01411 int i, j, m1_pos = 0, m2_pos = 0, r_pos = 0; 01412 it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols), 01413 "Mat<>::operator-(): Wrong sizes"); 01414 01415 for (i = 0; i < r.no_cols; i++) { 01416 for (j = 0; j < r.no_rows; j++) 01417 r.data[r_pos+j] = m1.data[m1_pos+j] - m2.data[m2_pos+j]; 01418 // next column 01419 m1_pos += m1.no_rows; 01420 m2_pos += m2.no_rows; 01421 r_pos += r.no_rows; 01422 } 01423 01424 return r; 01425 } 01426 01427 template<class Num_T> inline 01428 Mat<Num_T>& Mat<Num_T>::operator-=(Num_T t) 01429 { 01430 for (int i = 0; i < datasize; i++) 01431 data[i] -= t; 01432 return *this; 01433 } 01434 01435 template<class Num_T> 01436 Mat<Num_T> operator-(const Mat<Num_T> &m, Num_T t) 01437 { 01438 Mat<Num_T> r(m.no_rows, m.no_cols); 01439 int i, j, m_pos = 0, r_pos = 0; 01440 01441 for (i = 0; i < r.no_cols; i++) { 01442 for (j = 0; j < r.no_rows; j++) 01443 r.data[r_pos+j] = m.data[m_pos+j] - t; 01444 // next column 01445 m_pos += m.no_rows; 01446 r_pos += r.no_rows; 01447 } 01448 01449 return r; 01450 } 01451 01452 template<class Num_T> 01453 Mat<Num_T> operator-(Num_T t, const Mat<Num_T> &m) 01454 { 01455 Mat<Num_T> r(m.no_rows, m.no_cols); 01456 int i, j, m_pos = 0, r_pos = 0; 01457 01458 for (i = 0; i < r.no_cols; i++) { 01459 for (j = 0; j < r.no_rows; j++) 01460 r.data[r_pos+j] = t - m.data[m_pos+j]; 01461 // next column 01462 m_pos += m.no_rows; 01463 r_pos += r.no_rows; 01464 } 01465 01466 return r; 01467 } 01468 01469 template<class Num_T> 01470 Mat<Num_T> operator-(const Mat<Num_T> &m) 01471 { 01472 Mat<Num_T> r(m.no_rows, m.no_cols); 01473 int i, j, m_pos = 0, r_pos = 0; 01474 01475 for (i = 0; i < r.no_cols; i++) { 01476 for (j = 0; j < r.no_rows; j++) 01477 r.data[r_pos+j] = -m.data[m_pos+j]; 01478 // next column 01479 m_pos += m.no_rows; 01480 r_pos += r.no_rows; 01481 } 01482 01483 return r; 01484 } 01485 01486 #if defined(HAVE_BLAS) 01487 template<> mat& mat::operator*=(const mat &m); 01488 template<> cmat& cmat::operator*=(const cmat &m); 01489 #endif 01490 01491 template<class Num_T> 01492 Mat<Num_T>& Mat<Num_T>::operator*=(const Mat<Num_T> &m) 01493 { 01494 it_assert_debug(no_cols == m.no_rows, "Mat<>::operator*=(): Wrong sizes"); 01495 Mat<Num_T> r(no_rows, m.no_cols); 01496 01497 Num_T tmp; 01498 01499 int i, j, k, r_pos = 0, pos = 0, m_pos = 0; 01500 01501 for (i = 0; i < r.no_cols; i++) { 01502 for (j = 0; j < r.no_rows; j++) { 01503 tmp = Num_T(0); 01504 pos = 0; 01505 for (k = 0; k < no_cols; k++) { 01506 tmp += data[pos+j] * m.data[m_pos+k]; 01507 pos += no_rows; 01508 } 01509 r.data[r_pos+j] = tmp; 01510 } 01511 r_pos += r.no_rows; 01512 m_pos += m.no_rows; 01513 } 01514 operator=(r); // time consuming 01515 return *this; 01516 } 01517 01518 template<class Num_T> inline 01519 Mat<Num_T>& Mat<Num_T>::operator*=(Num_T t) 01520 { 01521 scal_vector(datasize, t, data); 01522 return *this; 01523 } 01524 01525 #if defined(HAVE_BLAS) 01526 template<> mat operator*(const mat &m1, const mat &m2); 01527 template<> cmat operator*(const cmat &m1, const cmat &m2); 01528 #endif 01529 01530 01531 template<class Num_T> 01532 Mat<Num_T> operator*(const Mat<Num_T> &m1, const Mat<Num_T> &m2) 01533 { 01534 it_assert_debug(m1.no_cols == m2.no_rows, 01535 "Mat<>::operator*(): Wrong sizes"); 01536 Mat<Num_T> r(m1.no_rows, m2.no_cols); 01537 01538 Num_T tmp; 01539 int i, j, k; 01540 Num_T *tr = r.data, *t1, *t2 = m2.data; 01541 01542 for (i = 0; i < r.no_cols; i++) { 01543 for (j = 0; j < r.no_rows; j++) { 01544 tmp = Num_T(0); 01545 t1 = m1.data + j; 01546 for (k = m1.no_cols; k > 0; k--) { 01547 tmp += *(t1) * *(t2++); 01548 t1 += m1.no_rows; 01549 } 01550 *(tr++) = tmp; 01551 t2 -= m2.no_rows; 01552 } 01553 t2 += m2.no_rows; 01554 } 01555 01556 return r; 01557 } 01558 01559 #if defined(HAVE_BLAS) 01560 template<> vec operator*(const mat &m, const vec &v); 01561 template<> cvec operator*(const cmat &m, const cvec &v); 01562 #endif 01563 01564 template<class Num_T> 01565 Vec<Num_T> operator*(const Mat<Num_T> &m, const Vec<Num_T> &v) 01566 { 01567 it_assert_debug(m.no_cols == v.size(), 01568 "Mat<>::operator*(): Wrong sizes"); 01569 Vec<Num_T> r(m.no_rows); 01570 int i, k, m_pos; 01571 01572 for (i = 0; i < m.no_rows; i++) { 01573 r(i) = Num_T(0); 01574 m_pos = 0; 01575 for (k = 0; k < m.no_cols; k++) { 01576 r(i) += m.data[m_pos+i] * v(k); 01577 m_pos += m.no_rows; 01578 } 01579 } 01580 01581 return r; 01582 } 01583 01584 template<class Num_T> 01585 Mat<Num_T> operator*(const Vec<Num_T> &v, const Mat<Num_T> &m) 01586 { 01587 it_assert((m.no_rows == 1), "Mat<Num_T>::operator*(): wrong sizes"); 01588 it_warning("Mat<Num_T>::operator*(v, m): This operator is deprecated. " 01589 "Please use outer_product(v, m.get_row(0)) instead."); 01590 return outer_product(v, m.get_row(0)); 01591 } 01592 01593 template<class Num_T> 01594 Mat<Num_T> operator*(const Mat<Num_T> &m, Num_T t) 01595 { 01596 Mat<Num_T> r(m.no_rows, m.no_cols); 01597 01598 for (int i = 0; i < r.datasize; i++) 01599 r.data[i] = m.data[i] * t; 01600 01601 return r; 01602 } 01603 01604 template<class Num_T> inline 01605 Mat<Num_T> operator*(Num_T t, const Mat<Num_T> &m) 01606 { 01607 return operator*(m, t); 01608 } 01609 01610 template<class Num_T> inline 01611 Mat<Num_T> elem_mult(const Mat<Num_T> &m1, const Mat<Num_T> &m2) 01612 { 01613 Mat<Num_T> out; 01614 elem_mult_out(m1, m2, out); 01615 return out; 01616 } 01617 01618 template<class Num_T> 01619 void elem_mult_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2, 01620 Mat<Num_T> &out) 01621 { 01622 it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols), 01623 "Mat<>::elem_mult_out(): Wrong sizes"); 01624 out.set_size(m1.no_rows, m1.no_cols); 01625 for (int i = 0; i < out.datasize; i++) 01626 out.data[i] = m1.data[i] * m2.data[i]; 01627 } 01628 01629 template<class Num_T> 01630 void elem_mult_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2, 01631 const Mat<Num_T> &m3, Mat<Num_T> &out) 01632 { 01633 it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_rows == m3.no_rows) 01634 && (m1.no_cols == m2.no_cols) && (m1.no_cols == m3.no_cols), 01635 "Mat<>::elem_mult_out(): Wrong sizes"); 01636 out.set_size(m1.no_rows, m1.no_cols); 01637 for (int i = 0; i < out.datasize; i++) 01638 out.data[i] = m1.data[i] * m2.data[i] * m3.data[i]; 01639 } 01640 01641 template<class Num_T> 01642 void elem_mult_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2, 01643 const Mat<Num_T> &m3, const Mat<Num_T> &m4, 01644 Mat<Num_T> &out) 01645 { 01646 it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_rows == m3.no_rows) 01647 && (m1.no_rows == m4.no_rows) && (m1.no_cols == m2.no_cols) 01648 && (m1.no_cols == m3.no_cols) && (m1.no_cols == m4.no_cols), 01649 "Mat<>::elem_mult_out(): Wrong sizes"); 01650 out.set_size(m1.no_rows, m1.no_cols); 01651 for (int i = 0; i < out.datasize; i++) 01652 out.data[i] = m1.data[i] * m2.data[i] * m3.data[i] * m4.data[i]; 01653 } 01654 01655 template<class Num_T> inline 01656 void elem_mult_inplace(const Mat<Num_T> &m1, Mat<Num_T> &m2) 01657 { 01658 it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols), 01659 "Mat<>::elem_mult_inplace(): Wrong sizes"); 01660 for (int i = 0; i < m2.datasize; i++) 01661 m2.data[i] *= m1.data[i]; 01662 } 01663 01664 template<class Num_T> inline 01665 Num_T elem_mult_sum(const Mat<Num_T> &m1, const Mat<Num_T> &m2) 01666 { 01667 it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols), 01668 "Mat<>::elem_mult_sum(): Wrong sizes"); 01669 Num_T acc = 0; 01670 01671 for (int i = 0; i < m1.datasize; i++) 01672 acc += m1.data[i] * m2.data[i]; 01673 01674 return acc; 01675 } 01676 01677 template<class Num_T> inline 01678 Mat<Num_T>& Mat<Num_T>::operator/=(Num_T t) 01679 { 01680 for (int i = 0; i < datasize; i++) 01681 data[i] /= t; 01682 return *this; 01683 } 01684 01685 template<class Num_T> 01686 Mat<Num_T> operator/(const Mat<Num_T> &m, Num_T t) 01687 { 01688 Mat<Num_T> r(m.no_rows, m.no_cols); 01689 01690 for (int i = 0; i < r.datasize; i++) 01691 r.data[i] = m.data[i] / t; 01692 01693 return r; 01694 } 01695 01696 template<class Num_T> inline 01697 Mat<Num_T>& Mat<Num_T>::operator/=(const Mat<Num_T> &m) 01698 { 01699 it_assert_debug((m.no_rows == no_rows) && (m.no_cols == no_cols), 01700 "Mat<>::operator/=(): Wrong sizes"); 01701 for (int i = 0; i < datasize; i++) 01702 data[i] /= m.data[i]; 01703 return *this; 01704 } 01705 01706 template<class Num_T> inline 01707 Mat<Num_T> elem_div(const Mat<Num_T> &m1, const Mat<Num_T> &m2) 01708 { 01709 Mat<Num_T> out; 01710 elem_div_out(m1, m2, out); 01711 return out; 01712 } 01713 01714 template<class Num_T> 01715 void elem_div_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2, 01716 Mat<Num_T> &out) 01717 { 01718 it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols), 01719 "Mat<>::elem_div_out(): Wrong sizes"); 01720 01721 if ((out.no_rows != m1.no_rows) || (out.no_cols != m1.no_cols)) 01722 out.set_size(m1.no_rows, m1.no_cols); 01723 01724 for (int i = 0; i < out.datasize; i++) 01725 out.data[i] = m1.data[i] / m2.data[i]; 01726 } 01727 01728 template<class Num_T> inline 01729 Num_T elem_div_sum(const Mat<Num_T> &m1, const Mat<Num_T> &m2) 01730 { 01731 it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols), 01732 "Mat<>::elem_div_sum(): Wrong sizes"); 01733 Num_T acc = 0; 01734 01735 for (int i = 0; i < m1.datasize; i++) 01736 acc += m1.data[i] / m2.data[i]; 01737 01738 return acc; 01739 } 01740 01741 template<class Num_T> 01742 bool Mat<Num_T>::operator==(const Mat<Num_T> &m) const 01743 { 01744 if (no_rows != m.no_rows || no_cols != m.no_cols) return false; 01745 for (int i = 0;i < datasize;i++) { 01746 if (data[i] != m.data[i]) return false; 01747 } 01748 return true; 01749 } 01750 01751 template<class Num_T> 01752 bool Mat<Num_T>::operator!=(const Mat<Num_T> &m) const 01753 { 01754 if (no_rows != m.no_rows || no_cols != m.no_cols) return true; 01755 for (int i = 0;i < datasize;i++) { 01756 if (data[i] != m.data[i]) return true; 01757 } 01758 return false; 01759 } 01760 01761 template <class Num_T> 01762 std::ostream &operator<<(std::ostream &os, const Mat<Num_T> &m) 01763 { 01764 int i; 01765 01766 switch (m.rows()) { 01767 case 0 : 01768 os << "[]"; 01769 break; 01770 case 1 : 01771 os << '[' << m.get_row(0) << ']'; 01772 break; 01773 default: 01774 os << '[' << m.get_row(0) << std::endl; 01775 for (i = 1; i < m.rows() - 1; i++) 01776 os << ' ' << m.get_row(i) << std::endl; 01777 os << ' ' << m.get_row(m.rows() - 1) << ']'; 01778 } 01779 01780 return os; 01781 } 01782 01783 template <class Num_T> 01784 std::istream &operator>>(std::istream &is, Mat<Num_T> &m) 01785 { 01786 std::ostringstream buffer; 01787 bool started = false; 01788 bool finished = false; 01789 bool brackets = false; 01790 bool within_double_brackets = false; 01791 char c; 01792 01793 while (!finished) { 01794 if (is.eof()) { 01795 finished = true; 01796 } 01797 else { 01798 is.get(c); 01799 01800 if (is.eof() || (c == '\n')) { 01801 if (brackets) { 01802 // Right bracket missing 01803 is.setstate(std::ios_base::failbit); 01804 finished = true; 01805 } 01806 else if (!((c == '\n') && !started)) { 01807 finished = true; 01808 } 01809 } 01810 else if ((c == ' ') || (c == '\t')) { 01811 if (started) { 01812 buffer << ' '; 01813 } 01814 } 01815 else if (c == '[') { 01816 if ((started && !brackets) || within_double_brackets) { 01817 // Unexpected left bracket 01818 is.setstate(std::ios_base::failbit); 01819 finished = true; 01820 } 01821 else if (!started) { 01822 started = true; 01823 brackets = true; 01824 } 01825 else { 01826 within_double_brackets = true; 01827 } 01828 } 01829 else if (c == ']') { 01830 if (!started || !brackets) { 01831 // Unexpected right bracket 01832 is.setstate(std::ios_base::failbit); 01833 finished = true; 01834 } 01835 else if (within_double_brackets) { 01836 within_double_brackets = false; 01837 buffer << ';'; 01838 } 01839 else { 01840 finished = true; 01841 } 01842 while (!is.eof() && (((c = static_cast<char>(is.peek())) == ' ') 01843 || (c == '\t'))) { 01844 is.get(); 01845 } 01846 if (!is.eof() && (c == '\n')) { 01847 is.get(); 01848 } 01849 } 01850 else { 01851 started = true; 01852 buffer << c; 01853 } 01854 } 01855 } 01856 01857 if (!started) { 01858 m.set_size(0, false); 01859 } 01860 else { 01861 m.set(buffer.str()); 01862 } 01863 01864 return is; 01865 } 01866 01868 01869 // --------------------------------------------------------------------- 01870 // Instantiations 01871 // --------------------------------------------------------------------- 01872 01873 #ifdef HAVE_EXTERN_TEMPLATE 01874 01875 // class instantiations 01876 01877 extern template class Mat<double>; 01878 extern template class Mat<std::complex<double> >; 01879 extern template class Mat<int>; 01880 extern template class Mat<short int>; 01881 extern template class Mat<bin>; 01882 01883 // addition operators 01884 01885 extern template mat operator+(const mat &m1, const mat &m2); 01886 extern template cmat operator+(const cmat &m1, const cmat &m2); 01887 extern template imat operator+(const imat &m1, const imat &m2); 01888 extern template smat operator+(const smat &m1, const smat &m2); 01889 extern template bmat operator+(const bmat &m1, const bmat &m2); 01890 01891 extern template mat operator+(const mat &m, double t); 01892 extern template cmat operator+(const cmat &m, std::complex<double> t); 01893 extern template imat operator+(const imat &m, int t); 01894 extern template smat operator+(const smat &m, short t); 01895 extern template bmat operator+(const bmat &m, bin t); 01896 01897 extern template mat operator+(double t, const mat &m); 01898 extern template cmat operator+(std::complex<double> t, const cmat &m); 01899 extern template imat operator+(int t, const imat &m); 01900 extern template smat operator+(short t, const smat &m); 01901 extern template bmat operator+(bin t, const bmat &m); 01902 01903 // subtraction operators 01904 01905 extern template mat operator-(const mat &m1, const mat &m2); 01906 extern template cmat operator-(const cmat &m1, const cmat &m2); 01907 extern template imat operator-(const imat &m1, const imat &m2); 01908 extern template smat operator-(const smat &m1, const smat &m2); 01909 extern template bmat operator-(const bmat &m1, const bmat &m2); 01910 01911 extern template mat operator-(const mat &m, double t); 01912 extern template cmat operator-(const cmat &m, std::complex<double> t); 01913 extern template imat operator-(const imat &m, int t); 01914 extern template smat operator-(const smat &m, short t); 01915 extern template bmat operator-(const bmat &m, bin t); 01916 01917 extern template mat operator-(double t, const mat &m); 01918 extern template cmat operator-(std::complex<double> t, const cmat &m); 01919 extern template imat operator-(int t, const imat &m); 01920 extern template smat operator-(short t, const smat &m); 01921 extern template bmat operator-(bin t, const bmat &m); 01922 01923 // unary minus 01924 01925 extern template mat operator-(const mat &m); 01926 extern template cmat operator-(const cmat &m); 01927 extern template imat operator-(const imat &m); 01928 extern template smat operator-(const smat &m); 01929 extern template bmat operator-(const bmat &m); 01930 01931 // multiplication operators 01932 01933 #if !defined(HAVE_BLAS) 01934 extern template mat operator*(const mat &m1, const mat &m2); 01935 extern template cmat operator*(const cmat &m1, const cmat &m2); 01936 #endif 01937 extern template imat operator*(const imat &m1, const imat &m2); 01938 extern template smat operator*(const smat &m1, const smat &m2); 01939 extern template bmat operator*(const bmat &m1, const bmat &m2); 01940 01941 #if !defined(HAVE_BLAS) 01942 extern template vec operator*(const mat &m, const vec &v); 01943 extern template cvec operator*(const cmat &m, const cvec &v); 01944 #endif 01945 extern template ivec operator*(const imat &m, const ivec &v); 01946 extern template svec operator*(const smat &m, const svec &v); 01947 extern template bvec operator*(const bmat &m, const bvec &v); 01948 01949 extern template mat operator*(const vec &v, const mat &m); 01950 extern template cmat operator*(const cvec &v, const cmat &m); 01951 extern template imat operator*(const ivec &v, const imat &m); 01952 extern template smat operator*(const svec &v, const smat &m); 01953 extern template bmat operator*(const bvec &v, const bmat &m); 01954 01955 extern template mat operator*(const mat &m, double t); 01956 extern template cmat operator*(const cmat &m, std::complex<double> t); 01957 extern template imat operator*(const imat &m, int t); 01958 extern template smat operator*(const smat &m, short t); 01959 extern template bmat operator*(const bmat &m, bin t); 01960 01961 extern template mat operator*(double t, const mat &m); 01962 extern template cmat operator*(std::complex<double> t, const cmat &m); 01963 extern template imat operator*(int t, const imat &m); 01964 extern template smat operator*(short t, const smat &m); 01965 extern template bmat operator*(bin t, const bmat &m); 01966 01967 // element-wise multiplication 01968 01969 extern template mat elem_mult(const mat &m1, const mat &m2); 01970 extern template cmat elem_mult(const cmat &m1, const cmat &m2); 01971 extern template imat elem_mult(const imat &m1, const imat &m2); 01972 extern template smat elem_mult(const smat &m1, const smat &m2); 01973 extern template bmat elem_mult(const bmat &m1, const bmat &m2); 01974 01975 extern template void elem_mult_out(const mat &m1, const mat &m2, mat &out); 01976 extern template void elem_mult_out(const cmat &m1, const cmat &m2, 01977 cmat &out); 01978 extern template void elem_mult_out(const imat &m1, const imat &m2, 01979 imat &out); 01980 extern template void elem_mult_out(const smat &m1, const smat &m2, 01981 smat &out); 01982 extern template void elem_mult_out(const bmat &m1, const bmat &m2, 01983 bmat &out); 01984 01985 extern template void elem_mult_out(const mat &m1, const mat &m2, 01986 const mat &m3, mat &out); 01987 extern template void elem_mult_out(const cmat &m1, const cmat &m2, 01988 const cmat &m3, cmat &out); 01989 extern template void elem_mult_out(const imat &m1, const imat &m2, 01990 const imat &m3, imat &out); 01991 extern template void elem_mult_out(const smat &m1, const smat &m2, 01992 const smat &m3, smat &out); 01993 extern template void elem_mult_out(const bmat &m1, const bmat &m2, 01994 const bmat &m3, bmat &out); 01995 01996 extern template void elem_mult_out(const mat &m1, const mat &m2, 01997 const mat &m3, const mat &m4, mat &out); 01998 extern template void elem_mult_out(const cmat &m1, const cmat &m2, 01999 const cmat &m3, const cmat &m4, 02000 cmat &out); 02001 extern template void elem_mult_out(const imat &m1, const imat &m2, 02002 const imat &m3, const imat &m4, 02003 imat &out); 02004 extern template void elem_mult_out(const smat &m1, const smat &m2, 02005 const smat &m3, const smat &m4, 02006 smat &out); 02007 extern template void elem_mult_out(const bmat &m1, const bmat &m2, 02008 const bmat &m3, const bmat &m4, 02009 bmat &out); 02010 02011 extern template void elem_mult_inplace(const mat &m1, mat &m2); 02012 extern template void elem_mult_inplace(const cmat &m1, cmat &m2); 02013 extern template void elem_mult_inplace(const imat &m1, imat &m2); 02014 extern template void elem_mult_inplace(const smat &m1, smat &m2); 02015 extern template void elem_mult_inplace(const bmat &m1, bmat &m2); 02016 02017 extern template double elem_mult_sum(const mat &m1, const mat &m2); 02018 extern template std::complex<double> elem_mult_sum(const cmat &m1, 02019 const cmat &m2); 02020 extern template int elem_mult_sum(const imat &m1, const imat &m2); 02021 extern template short elem_mult_sum(const smat &m1, const smat &m2); 02022 extern template bin elem_mult_sum(const bmat &m1, const bmat &m2); 02023 02024 // division operator 02025 02026 extern template mat operator/(const mat &m, double t); 02027 extern template cmat operator/(const cmat &m, std::complex<double> t); 02028 extern template imat operator/(const imat &m, int t); 02029 extern template smat operator/(const smat &m, short t); 02030 extern template bmat operator/(const bmat &m, bin t); 02031 02032 // element-wise division 02033 02034 extern template mat elem_div(const mat &m1, const mat &m2); 02035 extern template cmat elem_div(const cmat &m1, const cmat &m2); 02036 extern template imat elem_div(const imat &m1, const imat &m2); 02037 extern template smat elem_div(const smat &m1, const smat &m2); 02038 extern template bmat elem_div(const bmat &m1, const bmat &m2); 02039 02040 extern template void elem_div_out(const mat &m1, const mat &m2, mat &out); 02041 extern template void elem_div_out(const cmat &m1, const cmat &m2, cmat &out); 02042 extern template void elem_div_out(const imat &m1, const imat &m2, imat &out); 02043 extern template void elem_div_out(const smat &m1, const smat &m2, smat &out); 02044 extern template void elem_div_out(const bmat &m1, const bmat &m2, bmat &out); 02045 02046 extern template double elem_div_sum(const mat &m1, const mat &m2); 02047 extern template std::complex<double> elem_div_sum(const cmat &m1, 02048 const cmat &m2); 02049 extern template int elem_div_sum(const imat &m1, const imat &m2); 02050 extern template short elem_div_sum(const smat &m1, const smat &m2); 02051 extern template bin elem_div_sum(const bmat &m1, const bmat &m2); 02052 02053 // concatenation 02054 02055 extern template mat concat_horizontal(const mat &m1, const mat &m2); 02056 extern template cmat concat_horizontal(const cmat &m1, const cmat &m2); 02057 extern template imat concat_horizontal(const imat &m1, const imat &m2); 02058 extern template smat concat_horizontal(const smat &m1, const smat &m2); 02059 extern template bmat concat_horizontal(const bmat &m1, const bmat &m2); 02060 02061 extern template mat concat_vertical(const mat &m1, const mat &m2); 02062 extern template cmat concat_vertical(const cmat &m1, const cmat &m2); 02063 extern template imat concat_vertical(const imat &m1, const imat &m2); 02064 extern template smat concat_vertical(const smat &m1, const smat &m2); 02065 extern template bmat concat_vertical(const bmat &m1, const bmat &m2); 02066 02067 // I/O streams 02068 02069 extern template std::ostream &operator<<(std::ostream &os, const mat &m); 02070 extern template std::ostream &operator<<(std::ostream &os, const cmat &m); 02071 extern template std::ostream &operator<<(std::ostream &os, const imat &m); 02072 extern template std::ostream &operator<<(std::ostream &os, const smat &m); 02073 extern template std::ostream &operator<<(std::ostream &os, const bmat &m); 02074 02075 extern template std::istream &operator>>(std::istream &is, mat &m); 02076 extern template std::istream &operator>>(std::istream &is, cmat &m); 02077 extern template std::istream &operator>>(std::istream &is, imat &m); 02078 extern template std::istream &operator>>(std::istream &is, smat &m); 02079 extern template std::istream &operator>>(std::istream &is, bmat &m); 02080 02081 #endif // HAVE_EXTERN_TEMPLATE 02082 02084 02085 } // namespace itpp 02086 02087 #endif // #ifndef MAT_H
Generated on Fri Jul 25 12:42:58 2008 for IT++ by Doxygen 1.5.4