IT++ Logo
mat.h
Go to the documentation of this file.
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>
01656 #ifndef _MSC_VER
01657 inline
01658 #endif
01659 void elem_mult_inplace(const Mat<Num_T> &m1, Mat<Num_T> &m2)
01660 {
01661   it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols),
01662                   "Mat<>::elem_mult_inplace(): Wrong sizes");
01663   for (int i = 0; i < m2.datasize; i++)
01664     m2.data[i] *= m1.data[i];
01665 }
01666 
01667 template<class Num_T> inline
01668 Num_T elem_mult_sum(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
01669 {
01670   it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols),
01671                   "Mat<>::elem_mult_sum(): Wrong sizes");
01672   Num_T acc = 0;
01673 
01674   for (int i = 0; i < m1.datasize; i++)
01675     acc += m1.data[i] * m2.data[i];
01676 
01677   return acc;
01678 }
01679 
01680 template<class Num_T> inline
01681 Mat<Num_T>& Mat<Num_T>::operator/=(Num_T t)
01682 {
01683   for (int i = 0; i < datasize; i++)
01684     data[i] /= t;
01685   return *this;
01686 }
01687 
01688 template<class Num_T>
01689 Mat<Num_T> operator/(const Mat<Num_T> &m, Num_T t)
01690 {
01691   Mat<Num_T> r(m.no_rows, m.no_cols);
01692 
01693   for (int i = 0; i < r.datasize; i++)
01694     r.data[i] = m.data[i] / t;
01695 
01696   return r;
01697 }
01698 
01699 template<class Num_T> inline
01700 Mat<Num_T>& Mat<Num_T>::operator/=(const Mat<Num_T> &m)
01701 {
01702   it_assert_debug((m.no_rows == no_rows) && (m.no_cols == no_cols),
01703                   "Mat<>::operator/=(): Wrong sizes");
01704   for (int i = 0; i < datasize; i++)
01705     data[i] /= m.data[i];
01706   return *this;
01707 }
01708 
01709 template<class Num_T> inline
01710 Mat<Num_T> elem_div(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
01711 {
01712   Mat<Num_T> out;
01713   elem_div_out(m1, m2, out);
01714   return out;
01715 }
01716 
01717 template<class Num_T>
01718 void elem_div_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2,
01719                   Mat<Num_T> &out)
01720 {
01721   it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols),
01722                   "Mat<>::elem_div_out(): Wrong sizes");
01723 
01724   if ((out.no_rows != m1.no_rows) || (out.no_cols != m1.no_cols))
01725     out.set_size(m1.no_rows, m1.no_cols);
01726 
01727   for (int i = 0; i < out.datasize; i++)
01728     out.data[i] = m1.data[i] / m2.data[i];
01729 }
01730 
01731 template<class Num_T> inline
01732 Num_T elem_div_sum(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
01733 {
01734   it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols),
01735                   "Mat<>::elem_div_sum(): Wrong sizes");
01736   Num_T acc = 0;
01737 
01738   for (int i = 0; i < m1.datasize; i++)
01739     acc += m1.data[i] / m2.data[i];
01740 
01741   return acc;
01742 }
01743 
01744 template<class Num_T>
01745 bool Mat<Num_T>::operator==(const Mat<Num_T> &m) const
01746 {
01747   if (no_rows != m.no_rows || no_cols != m.no_cols) return false;
01748   for (int i = 0;i < datasize;i++) {
01749     if (data[i] != m.data[i]) return false;
01750   }
01751   return true;
01752 }
01753 
01754 template<class Num_T>
01755 bool Mat<Num_T>::operator!=(const Mat<Num_T> &m) const
01756 {
01757   if (no_rows != m.no_rows || no_cols != m.no_cols) return true;
01758   for (int i = 0;i < datasize;i++) {
01759     if (data[i] != m.data[i]) return true;
01760   }
01761   return false;
01762 }
01763 
01764 template <class Num_T>
01765 std::ostream &operator<<(std::ostream &os, const Mat<Num_T> &m)
01766 {
01767   int i;
01768 
01769   switch (m.rows()) {
01770   case 0 :
01771     os << "[]";
01772     break;
01773   case 1 :
01774     os << '[' << m.get_row(0) << ']';
01775     break;
01776   default:
01777     os << '[' << m.get_row(0) << std::endl;
01778     for (i = 1; i < m.rows() - 1; i++)
01779       os << ' ' << m.get_row(i) << std::endl;
01780     os << ' ' << m.get_row(m.rows() - 1) << ']';
01781   }
01782 
01783   return os;
01784 }
01785 
01786 template <class Num_T>
01787 std::istream &operator>>(std::istream &is, Mat<Num_T> &m)
01788 {
01789   std::ostringstream buffer;
01790   bool started = false;
01791   bool finished = false;
01792   bool brackets = false;
01793   bool within_double_brackets = false;
01794   char c;
01795 
01796   while (!finished) {
01797     if (is.eof()) {
01798       finished = true;
01799     }
01800     else {
01801       is.get(c);
01802 
01803       if (is.eof() || (c == '\n')) {
01804         if (brackets) {
01805           // Right bracket missing
01806           is.setstate(std::ios_base::failbit);
01807           finished = true;
01808         }
01809         else if (!((c == '\n') && !started)) {
01810           finished = true;
01811         }
01812       }
01813       else if ((c == ' ') || (c == '\t')) {
01814         if (started) {
01815           buffer << ' ';
01816         }
01817       }
01818       else if (c == '[') {
01819         if ((started && !brackets) || within_double_brackets) {
01820           // Unexpected left bracket
01821           is.setstate(std::ios_base::failbit);
01822           finished = true;
01823         }
01824         else if (!started) {
01825           started = true;
01826           brackets = true;
01827         }
01828         else {
01829           within_double_brackets = true;
01830         }
01831       }
01832       else if (c == ']') {
01833         if (!started || !brackets) {
01834           // Unexpected right bracket
01835           is.setstate(std::ios_base::failbit);
01836           finished = true;
01837         }
01838         else if (within_double_brackets) {
01839           within_double_brackets = false;
01840           buffer << ';';
01841         }
01842         else {
01843           finished = true;
01844         }
01845         while (!is.eof() && (((c = static_cast<char>(is.peek())) == ' ')
01846                              || (c == '\t'))) {
01847           is.get();
01848         }
01849         if (!is.eof() && (c == '\n')) {
01850           is.get();
01851         }
01852       }
01853       else {
01854         started = true;
01855         buffer << c;
01856       }
01857     }
01858   }
01859 
01860   if (!started) {
01861     m.set_size(0, false);
01862   }
01863   else {
01864     m.set(buffer.str());
01865   }
01866 
01867   return is;
01868 }
01869 
01871 
01872 // ---------------------------------------------------------------------
01873 // Instantiations
01874 // ---------------------------------------------------------------------
01875 
01876 #ifdef HAVE_EXTERN_TEMPLATE
01877 
01878 // class instantiations
01879 
01880 extern template class Mat<double>;
01881 extern template class Mat<std::complex<double> >;
01882 extern template class Mat<int>;
01883 extern template class Mat<short int>;
01884 extern template class Mat<bin>;
01885 
01886 // addition operators
01887 
01888 extern template mat operator+(const mat &m1, const mat &m2);
01889 extern template cmat operator+(const cmat &m1, const cmat &m2);
01890 extern template imat operator+(const imat &m1, const imat &m2);
01891 extern template smat operator+(const smat &m1, const smat &m2);
01892 extern template bmat operator+(const bmat &m1, const bmat &m2);
01893 
01894 extern template mat operator+(const mat &m, double t);
01895 extern template cmat operator+(const cmat &m, std::complex<double> t);
01896 extern template imat operator+(const imat &m, int t);
01897 extern template smat operator+(const smat &m, short t);
01898 extern template bmat operator+(const bmat &m, bin t);
01899 
01900 extern template mat operator+(double t, const mat &m);
01901 extern template cmat operator+(std::complex<double> t, const cmat &m);
01902 extern template imat operator+(int t, const imat &m);
01903 extern template smat operator+(short t, const smat &m);
01904 extern template bmat operator+(bin t, const bmat &m);
01905 
01906 // subtraction operators
01907 
01908 extern template mat operator-(const mat &m1, const mat &m2);
01909 extern template cmat operator-(const cmat &m1, const cmat &m2);
01910 extern template imat operator-(const imat &m1, const imat &m2);
01911 extern template smat operator-(const smat &m1, const smat &m2);
01912 extern template bmat operator-(const bmat &m1, const bmat &m2);
01913 
01914 extern template mat operator-(const mat &m, double t);
01915 extern template cmat operator-(const cmat &m, std::complex<double> t);
01916 extern template imat operator-(const imat &m, int t);
01917 extern template smat operator-(const smat &m, short t);
01918 extern template bmat operator-(const bmat &m, bin t);
01919 
01920 extern template mat operator-(double t, const mat &m);
01921 extern template cmat operator-(std::complex<double> t, const cmat &m);
01922 extern template imat operator-(int t, const imat &m);
01923 extern template smat operator-(short t, const smat &m);
01924 extern template bmat operator-(bin t, const bmat &m);
01925 
01926 // unary minus
01927 
01928 extern template mat operator-(const mat &m);
01929 extern template cmat operator-(const cmat &m);
01930 extern template imat operator-(const imat &m);
01931 extern template smat operator-(const smat &m);
01932 extern template bmat operator-(const bmat &m);
01933 
01934 // multiplication operators
01935 
01936 #if !defined(HAVE_BLAS)
01937 extern template mat operator*(const mat &m1, const mat &m2);
01938 extern template cmat operator*(const cmat &m1, const cmat &m2);
01939 #endif
01940 extern template imat operator*(const imat &m1, const imat &m2);
01941 extern template smat operator*(const smat &m1, const smat &m2);
01942 extern template bmat operator*(const bmat &m1, const bmat &m2);
01943 
01944 #if !defined(HAVE_BLAS)
01945 extern template vec operator*(const mat &m, const vec &v);
01946 extern template cvec operator*(const cmat &m, const cvec &v);
01947 #endif
01948 extern template ivec operator*(const imat &m, const ivec &v);
01949 extern template svec operator*(const smat &m, const svec &v);
01950 extern template bvec operator*(const bmat &m, const bvec &v);
01951 
01952 extern template mat operator*(const vec &v, const mat &m);
01953 extern template cmat operator*(const cvec &v, const cmat &m);
01954 extern template imat operator*(const ivec &v, const imat &m);
01955 extern template smat operator*(const svec &v, const smat &m);
01956 extern template bmat operator*(const bvec &v, const bmat &m);
01957 
01958 extern template mat operator*(const mat &m, double t);
01959 extern template cmat operator*(const cmat &m, std::complex<double> t);
01960 extern template imat operator*(const imat &m, int t);
01961 extern template smat operator*(const smat &m, short t);
01962 extern template bmat operator*(const bmat &m, bin t);
01963 
01964 extern template mat operator*(double t, const mat &m);
01965 extern template cmat operator*(std::complex<double> t, const cmat &m);
01966 extern template imat operator*(int t, const imat &m);
01967 extern template smat operator*(short t, const smat &m);
01968 extern template bmat operator*(bin t, const bmat &m);
01969 
01970 // element-wise multiplication
01971 
01972 extern template mat elem_mult(const mat &m1, const mat &m2);
01973 extern template cmat elem_mult(const cmat &m1, const cmat &m2);
01974 extern template imat elem_mult(const imat &m1, const imat &m2);
01975 extern template smat elem_mult(const smat &m1, const smat &m2);
01976 extern template bmat elem_mult(const bmat &m1, const bmat &m2);
01977 
01978 extern template void elem_mult_out(const mat &m1, const mat &m2, mat &out);
01979 extern template void elem_mult_out(const cmat &m1, const cmat &m2,
01980                                      cmat &out);
01981 extern template void elem_mult_out(const imat &m1, const imat &m2,
01982                                      imat &out);
01983 extern template void elem_mult_out(const smat &m1, const smat &m2,
01984                                      smat &out);
01985 extern template void elem_mult_out(const bmat &m1, const bmat &m2,
01986                                      bmat &out);
01987 
01988 extern template void elem_mult_out(const mat &m1, const mat &m2,
01989                                      const mat &m3, mat &out);
01990 extern template void elem_mult_out(const cmat &m1, const cmat &m2,
01991                                      const cmat &m3, cmat &out);
01992 extern template void elem_mult_out(const imat &m1, const imat &m2,
01993                                      const imat &m3, imat &out);
01994 extern template void elem_mult_out(const smat &m1, const smat &m2,
01995                                      const smat &m3, smat &out);
01996 extern template void elem_mult_out(const bmat &m1, const bmat &m2,
01997                                      const bmat &m3, bmat &out);
01998 
01999 extern template void elem_mult_out(const mat &m1, const mat &m2,
02000                                      const mat &m3, const mat &m4, mat &out);
02001 extern template void elem_mult_out(const cmat &m1, const cmat &m2,
02002                                      const cmat &m3, const cmat &m4,
02003                                      cmat &out);
02004 extern template void elem_mult_out(const imat &m1, const imat &m2,
02005                                      const imat &m3, const imat &m4,
02006                                      imat &out);
02007 extern template void elem_mult_out(const smat &m1, const smat &m2,
02008                                      const smat &m3, const smat &m4,
02009                                      smat &out);
02010 extern template void elem_mult_out(const bmat &m1, const bmat &m2,
02011                                      const bmat &m3, const bmat &m4,
02012                                      bmat &out);
02013 
02014 extern template void elem_mult_inplace(const mat &m1, mat &m2);
02015 extern template void elem_mult_inplace(const cmat &m1, cmat &m2);
02016 extern template void elem_mult_inplace(const imat &m1, imat &m2);
02017 extern template void elem_mult_inplace(const smat &m1, smat &m2);
02018 extern template void elem_mult_inplace(const bmat &m1, bmat &m2);
02019 
02020 extern template double elem_mult_sum(const mat &m1, const mat &m2);
02021 extern template std::complex<double> elem_mult_sum(const cmat &m1,
02022     const cmat &m2);
02023 extern template int elem_mult_sum(const imat &m1, const imat &m2);
02024 extern template short elem_mult_sum(const smat &m1, const smat &m2);
02025 extern template bin elem_mult_sum(const bmat &m1, const bmat &m2);
02026 
02027 // division operator
02028 
02029 extern template mat operator/(const mat &m, double t);
02030 extern template cmat operator/(const cmat &m, std::complex<double> t);
02031 extern template imat operator/(const imat &m, int t);
02032 extern template smat operator/(const smat &m, short t);
02033 extern template bmat operator/(const bmat &m, bin t);
02034 
02035 // element-wise division
02036 
02037 extern template mat elem_div(const mat &m1, const mat &m2);
02038 extern template cmat elem_div(const cmat &m1, const cmat &m2);
02039 extern template imat elem_div(const imat &m1, const imat &m2);
02040 extern template smat elem_div(const smat &m1, const smat &m2);
02041 extern template bmat elem_div(const bmat &m1, const bmat &m2);
02042 
02043 extern template void elem_div_out(const mat &m1, const mat &m2, mat &out);
02044 extern template void elem_div_out(const cmat &m1, const cmat &m2, cmat &out);
02045 extern template void elem_div_out(const imat &m1, const imat &m2, imat &out);
02046 extern template void elem_div_out(const smat &m1, const smat &m2, smat &out);
02047 extern template void elem_div_out(const bmat &m1, const bmat &m2, bmat &out);
02048 
02049 extern template double elem_div_sum(const mat &m1, const mat &m2);
02050 extern template std::complex<double> elem_div_sum(const cmat &m1,
02051     const cmat &m2);
02052 extern template int elem_div_sum(const imat &m1, const imat &m2);
02053 extern template short elem_div_sum(const smat &m1, const smat &m2);
02054 extern template bin elem_div_sum(const bmat &m1, const bmat &m2);
02055 
02056 // concatenation
02057 
02058 extern template mat concat_horizontal(const mat &m1, const mat &m2);
02059 extern template cmat concat_horizontal(const cmat &m1, const cmat &m2);
02060 extern template imat concat_horizontal(const imat &m1, const imat &m2);
02061 extern template smat concat_horizontal(const smat &m1, const smat &m2);
02062 extern template bmat concat_horizontal(const bmat &m1, const bmat &m2);
02063 
02064 extern template mat concat_vertical(const mat &m1, const mat &m2);
02065 extern template cmat concat_vertical(const cmat &m1, const cmat &m2);
02066 extern template imat concat_vertical(const imat &m1, const imat &m2);
02067 extern template smat concat_vertical(const smat &m1, const smat &m2);
02068 extern template bmat concat_vertical(const bmat &m1, const bmat &m2);
02069 
02070 // I/O streams
02071 
02072 extern template std::ostream &operator<<(std::ostream &os, const mat  &m);
02073 extern template std::ostream &operator<<(std::ostream &os, const cmat &m);
02074 extern template std::ostream &operator<<(std::ostream &os, const imat  &m);
02075 extern template std::ostream &operator<<(std::ostream &os, const smat  &m);
02076 extern template std::ostream &operator<<(std::ostream &os, const bmat  &m);
02077 
02078 extern template std::istream &operator>>(std::istream &is, mat  &m);
02079 extern template std::istream &operator>>(std::istream &is, cmat &m);
02080 extern template std::istream &operator>>(std::istream &is, imat  &m);
02081 extern template std::istream &operator>>(std::istream &is, smat  &m);
02082 extern template std::istream &operator>>(std::istream &is, bmat  &m);
02083 
02084 #endif // HAVE_EXTERN_TEMPLATE
02085 
02087 
02088 } // namespace itpp
02089 
02090 #endif // #ifndef MAT_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
SourceForge Logo

Generated on Tue Dec 6 2011 16:51:46 for IT++ by Doxygen 1.7.4