Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

matrix.h

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*
00002  *                                   IT++                                    *
00003  *---------------------------------------------------------------------------*
00004  * Copyright (c) 1995-2002 by Tony Ottosson, Thomas Eriksson, Pål Frenger,   *
00005  * Tobias Ringström, and Jonas Samuelsson.                                   *
00006  *                                                                           *
00007  * Permission to use, copy, modify, and distribute this software and its     *
00008  * documentation under the terms of the GNU General Public License is hereby *
00009  * granted. No representations are made about the suitability of this        *
00010  * software for any purpose. It is provided "as is" without expressed or     *
00011  * implied warranty. See the GNU General Public License for more details.    *
00012  *---------------------------------------------------------------------------*/
00016 //  SPUC - Signal processing using C++ - A DSP library
00017 
00029 #ifndef _matrixh
00030 #define _matrixh
00031 
00032 #include <spuc.h>
00033 #include <iostream>
00034 #include <string>
00035 #include <cstdlib>
00036 #include <cstring>
00037 #include <spucconfig.h>
00038 #include <binary.h>
00039 #include <vector.h>
00040 #include <cmath>
00041 //#include <specmat.h>
00042 
00043 #ifdef HAVE_CBLAS
00044 #include "base/cblas.h"
00045 #endif
00046 
00047 #ifdef XXX
00048 using std::cout;
00049 using std::endl;
00050 using std::string;
00051 using std::ostream;
00052 using std::istream;
00053 using std::istringstream;
00054 using std::getline;
00055 using std::swap;
00056 #endif
00057 
00058 namespace SPUC {
00059 
00061 #define minimum(x,y) (((x)<(y)) ? (x) : (y))
00062 #define Matrix Mat
00063 
00064 template<class T> class Vec;
00065 template<class T> class Mat;
00066 class bin;
00067 
00068 // ----------------------------- Mat Friends -----------------------------
00069 
00071 template<class T> Mat<T> concat_horizontal(const Mat<T> &m1, const Mat<T> &m2);
00073 template<class T> Mat<T> concat_vertical(const Mat<T> &m1, const Mat<T> &m2);
00075 template<class T> Mat<T> operator+(const Mat<T> &m1, const Mat<T> &m2);
00077 template<class T> Mat<T> operator+(const Mat<T> &m, T t);
00079 template<class T> Mat<T> operator+(T t, const Mat<T> &m);
00081 template<class T> Mat<T> operator-(const Mat<T> &m1, const Mat<T> &m2);
00083 template<class T> Mat<T> operator-(const Mat<T> &m, T t);
00085 template<class T> Mat<T> operator-(T t, const Mat<T> &m);
00087 template<class T> Mat<T> operator-(const Mat<T> &m);
00089 template<class T> Mat<T> operator*(const Mat<T> &m1, const Mat<T> &m2);
00091 template<class T> Vec<T> operator*(const Mat<T> &m, const Vec<T> &v);
00093 template<class T> Vec<T> operator*(const Vec<T> &v, const Mat<T> &m);
00095 template<class T> Mat<T> operator*(const Mat<T> &m, T t);
00097 template<class T> Mat<T> operator*(T t, const Mat<T> &m);
00099 template<class T> Mat<T> elem_mult(const Mat<T> &m1, const Mat<T> &m2);
00101 template<class T> Mat<T> operator/(const Mat<T> &m, T t);
00103 template<class T> Mat<T> elem_div(const Mat<T> &m1, const Mat<T> &m2);
00104 
00162 template<class T>
00163 class Mat {
00164  public:
00166   Mat() { init(); }
00168   Mat(int inrow, int incol) {
00169     init(); 
00170 //      it_assert1(inrow>=0 && incol>=0, "The rows and columns must be >= 0");
00171     alloc(inrow, incol); }
00173   Mat(const Mat<T> &m);
00175   Mat(const Vec<T> &invector);
00179   Mat(const char *str) { init(); set(str); }
00180 
00187   Mat(T *c_array, int rows, int cols, bool RowMajor = true);
00188 
00190   ~Mat() { free(); }
00191     
00193   int cols() const { return no_cols; }
00195   int rows() const { return no_rows; }
00197   void set_size(int inrow, int incol, bool copy=false);
00199   void zeros();
00201   void clear() { zeros(); }
00203   void ones();
00205   bool set(const char *str);
00208 
00210   const T &operator()(int R,int C) const
00211     { 
00212 //        it_assert0(R>=0 && R<no_rows && C>=0 && C<no_cols, "Mat<T>::operator(): index out of range"); 
00213                  return data[R+C*no_rows]; }
00215   T &operator()(int R,int C)
00216     { 
00217 //        it_assert0(R>=0 && R<no_rows && C>=0 && C<no_cols, "Mat<T>::operator(): index out of range"); 
00218           return data[R+C*no_rows]; }
00220   T &operator()(int index)
00221     { 
00222 //        it_assert0(index<no_rows*no_cols && index>=0,"Mat<T>::operator(): index out of range");
00223     return data[index]; }
00225   const T &operator()(int index) const
00226     { 
00227 //        it_assert0(index<no_rows*no_cols && index>=0,"Mat<T>::operator(): index out of range");
00228     return data[index]; }
00229 
00235   const Mat<T> operator()(int r1, int r2, int c1, int c2) const;
00236 
00238   Vec<T> get_row(int Index) const ;
00240   Mat<T> get_rows(int r1, int r2) const;
00242   Mat<T> get_rows(const Vec<int> &indexlist) const;
00244   Vec<T> get_col(int Index) const ;
00246   Mat<T> get_cols(int c1, int c2) const;
00248   Mat<T> get_cols(const Vec<int> &indexlist) const;
00250   void set_row(int Index, const Vec<T> &invector);
00252   void set_col(int Index, const Vec<T> &invector);
00254   void copy_row(int to, int from);
00256   void copy_col(int to, int from);
00258   void swap_rows(int r1, int r2);
00260   void swap_cols(int c1, int c2);
00261 
00263   void set_submatrix(int r1, int r2, int c1, int c2, const Mat<T> &m);
00265   void set_submatrix(int r1, int r2, int c1, int c2, const T t);
00266 
00268   friend Mat<T> concat_horizontal TEMPLATE_FUN(const Mat<T> &m1, const Mat<T> &m2);
00270   friend Mat<T> concat_vertical TEMPLATE_FUN(const Mat<T> &m1, const Mat<T> &m2);
00271 
00273   void operator=(T t);
00275   void operator=(const Mat<T> &m);
00277   void operator=(const Vec<T> &v);
00279   void operator=(const char *values) { set(values); }
00280 
00282   void operator+=(const Mat<T> &m);
00284   void operator+=(T t);
00286   friend Mat<T> operator+TEMPLATE_FUN(const Mat<T> &m1, const Mat<T> &m2);
00288   friend Mat<T> operator+TEMPLATE_FUN(const Mat<T> &m, T t);
00290   friend Mat<T> operator+TEMPLATE_FUN(T t, const Mat<T> &m);
00291 
00293   void operator-=(const Mat<T> &m);
00295   void operator-=(T t);
00297   friend Mat<T> operator-TEMPLATE_FUN(const Mat<T> &m1, const Mat<T> &m2);
00299   friend Mat<T> operator-TEMPLATE_FUN(const Mat<T> &m, T t);
00301   friend Mat<T> operator-TEMPLATE_FUN(T t, const Mat<T> &m);
00303   friend Mat<T> operator-TEMPLATE_FUN(const Mat<T> &m);
00304 
00306   void operator*=(const Mat<T> &m);
00308   void operator*=(T t);
00310   friend Mat<T> operator*TEMPLATE_FUN(const Mat<T> &m1, const Mat<T> &m2);
00312   friend Vec<T> operator*TEMPLATE_FUN(const Mat<T> &m, const Vec<T> &v);
00314   friend Vec<T> operator*TEMPLATE_FUN(const Vec<T> &v, const Mat<T> &m);
00316   friend Mat<T> operator*TEMPLATE_FUN(const Mat<T> &m, T t);
00318   friend Mat<T> operator*TEMPLATE_FUN(T t, const Mat<T> &m);
00320   friend Mat<T> elem_mult TEMPLATE_FUN(const Mat<T> &m1, const Mat<T> &m2);
00321 
00323   void operator/=(T t);
00325   friend Mat<T> operator/TEMPLATE_FUN(const Mat<T> &m, T t);
00327   void operator/=(const Mat<T> &m);
00329   friend Mat<T> elem_div TEMPLATE_FUN(const Mat<T> &m1, const Mat<T> &m2);
00330 
00332   bool operator==(const Mat<T> &m) const;
00334   bool operator!=(const Mat<T> &m) const;
00335 
00337   T &_elem(int R,int C) {  return data[R+C*no_rows]; }
00339   const T &_elem(int R,int C) const {  return data[R+C*no_rows]; }
00341   T &_elem(int index) { return data[index]; }
00343   const T &_elem(int index) const { return data[index]; }
00344 
00346   T *_data() { return data; }
00348   const T *_data() const { return data; }
00350   int _datasize() const { return datasize; }
00351 
00352  protected:
00354   void alloc(int rows, int cols)
00355     {
00356       if ( datasize == rows * cols ) { // Reuse the memory
00357         no_rows = rows; no_cols = cols;
00358         return;
00359       }
00360       free();  // Free memory (if any allocated)
00361       if (rows == 0 || cols == 0)
00362         return;
00363       
00364       datasize = rows * cols;
00365       data = new T[datasize];
00366       no_rows = rows; no_cols = cols;
00367       
00368 //      it_assert1(data, "Mat<T>::alloc: Out of memory");
00369     }
00370 
00372   void free() { delete [] data; init(); }
00373 
00375   int datasize, no_rows, no_cols;
00376 
00378   T *data;
00379 
00380  private:
00381   void init()
00382     {
00383       data = 0;
00384       datasize = no_rows = no_cols = 0;
00385     }
00386 };
00387 
00388 
00389 
00394 #ifdef XXX
00395 template <class T>
00396 std::ostream &operator<<(std::ostream &os, const Mat<T> &m);
00397 
00402 template <class T>
00403 std::istream &operator>>(std::istream &is, Mat<T> &m);
00404 #endif
00405 
00409 typedef Mat<double> mat;
00410 
00415 typedef Mat<complex<double> > cmat;
00416 
00421 typedef Mat<int> imat;
00422 
00427 typedef Mat<long_long> llmat;
00428 
00433 typedef Mat<short int> smat;
00434 
00439 typedef Mat<bin> bmat;
00440 
00441 
00442 //------------------ Inline definitions ----------------------------
00443 
00444 template<class T> inline
00445 Mat<T>::Mat(T *c_array, int rows, int cols, bool RowMajor)
00446 {
00447   init();
00448   alloc(rows, cols);
00449   
00450   if (!RowMajor)
00451     memcpy(data, c_array, datasize*sizeof(T));
00452   else { // Row Major
00453     T *ptr = c_array;
00454     for (int i=0; i<rows; i++) {
00455       for (int j=0; j<cols; j++)
00456         data[i+j*no_rows] = *(ptr++);
00457     }
00458   }
00459 }
00460 
00461 
00462 template<class T> inline
00463 const Mat<T> Mat<T>::operator()(int r1, int r2, int c1, int c2) const
00464 {
00465   if (r1 == -1) r1 = no_rows-1;
00466   if (r2 == -1) r2 = no_rows-1;
00467   if (c1 == -1) c1 = no_cols-1;
00468   if (c2 == -1) c2 = no_cols-1;
00469 
00470 //  it_assert1(r1>=0 && r2>=0 && r1<no_rows && r2<no_rows &&
00471 //           c1>=0 && c2>=0 && c1<no_cols && c2<no_cols, "operator()(r1,r2,c1,c2)");
00472 
00473 //  it_assert1(r2>=r1 && c2>=c1, "Mat<T>::op(): r2>=r1 or c2>=c1 not fulfilled");
00474 
00475   Mat<T> s(r2-r1+1, c2-c1+1);
00476 
00477   for (int i=0;i<s.no_cols;i++)
00478     memcpy(s.data+i*s.no_rows, data+r1+(c1+i)*no_rows, s.no_rows*sizeof(T));
00479 
00480   return s;
00481 }
00482 // from mat.cpp
00483 template<class T> inline
00484 Mat<T>::Mat(const Mat<T> &m)
00485 { 
00486   init();
00487   alloc(m.no_rows, m.no_cols);
00488   copy_vector(m.datasize, m.data, data);
00489 }
00490 
00491 template<class T> inline
00492 Mat<T>::Mat(const Vec<T> &v)
00493 {
00494   init();
00495   set_size(v.length(), 1, false);
00496   set_col(0,v);
00497 }
00498 
00499 template<class T> inline
00500 void Mat<T>::set_size(int inrow, int incol, bool copy)
00501 {
00502 //  it_assert1(inrow>=0 && incol>=0, "Mat<T>::set_size: The rows and columns must be >= 0");
00503   if (no_rows!=inrow || no_cols!=incol) {
00504     if (copy) {
00505       Mat<T> temp(*this);
00506       int i, j;
00507       
00508       alloc(inrow, incol);
00509       for (i=0;i<inrow;i++)
00510         for (j=0;j<incol;j++)
00511           data[i+j*inrow] = (i<temp.no_rows && j<temp.no_cols) ? temp(i,j) : T(0);
00512     } else
00513       alloc(inrow, incol);
00514   }
00515 }
00516 
00517 template<class T> inline
00518 void Mat<T>::zeros()
00519 {
00520   for(int i=0; i<datasize; i++)
00521     data[i] = T(0);
00522 }
00523 
00524 template<class T> inline
00525 void Mat<T>::ones()
00526 {
00527   for(int i=0; i<datasize; i++)
00528     data[i] = T(1);
00529 }
00530 
00531 #ifndef DOXYGEN_SHOULD_SKIP_THIS 
00532 /* This piece of code generates the Doxygen warnings like "no matching class member found". However, the code is OK :-) */
00533 #ifdef XXX
00534 template<>
00535 bool bmat::set(const char *values)
00536 {
00537   istringstream buffer(values);         
00538   int rows=0, maxrows=10, cols=0, nocols=0, maxcols=10;
00539   short intemp;
00540 
00541   alloc(maxrows, maxcols);
00542         
00543   while(buffer.peek()!=EOF) {
00544     rows++;
00545     if (rows > maxrows) {
00546       maxrows *= 2;
00547       set_size(maxrows, maxcols, true);
00548     }
00549     cols=0;
00550     while(buffer.peek() != ';' && !buffer.eof()) {
00551       if (buffer.peek()==',') {
00552         buffer.get();
00553       } else {
00554         cols++;
00555         if (cols > nocols) {
00556           nocols=cols;
00557           if (cols > maxcols) {
00558             maxcols=maxcols*2;
00559             set_size(maxrows, maxcols, true);
00560           }
00561         }
00562         buffer >> intemp;
00563         this->operator()(rows-1,cols-1)=intemp;
00564       }
00565     }
00566     if (!buffer.eof())
00567       buffer.get();
00568   }
00569   set_size(rows, nocols, true);
00570 
00571   return true;
00572 }
00573 #endif
00574 #ifdef _MSC_VER
00575 #ifdef XZZ
00576 template<>
00577 bool llmat::set(const char *values)
00578 {
00579 //    it_error("set() does not work for llmat");
00580     return false;
00581 }
00582 #endif
00583 #endif /* _MSC_VER */
00584 
00585 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
00586 
00587 template<class T>
00588 bool Mat<T>::set(const char *values)
00589 {
00590   istringstream buffer(values); 
00591   int rows=0, maxrows=10, cols=0, nocols=0, maxcols=10;
00592 
00593   alloc(maxrows, maxcols);
00594         
00595   while(buffer.peek()!=EOF) {
00596     rows++;
00597     if (rows > maxrows) {
00598       maxrows=maxrows*2;
00599       set_size(maxrows, maxcols, true);
00600     }
00601     
00602     cols=0;
00603     while(buffer.peek() != ';' && !buffer.eof()) {
00604       if (buffer.peek()==',') {
00605         buffer.get();
00606       } else {
00607         cols++;
00608         if (cols > nocols) {
00609           nocols=cols;
00610           if (cols > maxcols) {
00611             maxcols=maxcols*2;
00612             set_size(maxrows, maxcols, true);
00613           }
00614         }
00615         buffer >> this->operator()(rows-1,cols-1);
00616       }
00617     }
00618     
00619     if (!buffer.eof())
00620       buffer.get();
00621   }
00622   set_size(rows, nocols, true);
00623 
00624   return true;
00625 }
00626 #ifdef XXX
00627 template<class T>
00628 bool Mat<T>::set(const std::string &str)
00629 {
00630     return set(str.c_str());
00631 }
00632 #endif
00633 template<class T> inline
00634 Vec<T> Mat<T>::get_row(int Index) const
00635 {
00636  //   it_assert1(Index>=0 && Index<no_rows, "Mat<T>::get_row: index out of range");
00637     Vec<T> a(no_cols);
00638 
00639     copy_vector(no_cols, data+Index, no_rows, a._data(), 1);
00640     return a;
00641 }
00642 
00643 template<class T>
00644 Mat<T> Mat<T>::get_rows(int r1, int r2) const
00645 {
00646  //   it_assert1(r1>=0 && r2<no_rows && r1<=r2, "Mat<T>::get_rows: index out of range");
00647     Mat<T> m(r2-r1+1, no_cols);
00648 
00649     for (int i=0; i<m.rows(); i++)
00650       copy_vector(no_cols, data+i+r1, no_rows, m.data+i, m.no_rows);
00651     
00652     return m;
00653 }
00654 
00655 template<class T>
00656 Mat<T> Mat<T>::get_rows(const Vec<int> &indexlist) const
00657 {
00658     Mat<T> m(indexlist.size(),no_cols);
00659 
00660     for (int i=0;i<indexlist.size();i++) {
00661 //      it_assert1(indexlist(i)>=0 && indexlist(i)<no_rows, "Mat<T>::get_rows: index out of range");
00662         copy_vector(no_cols, data+indexlist(i), no_rows, m.data+i, m.no_rows);
00663     }
00664 
00665     return m;
00666 }
00667 
00668 template<class T> inline
00669 Vec<T> Mat<T>::get_col(int Index) const
00670 {
00671 //    it_assert1(Index>=0 && Index<no_cols, "Mat<T>::get_col: index out of range");
00672     Vec<T> a(no_rows);
00673 
00674     copy_vector(no_rows, data+Index*no_rows, a._data());
00675 
00676     return a;
00677 }
00678 
00679 template<class T> inline
00680 Mat<T> Mat<T>::get_cols(int c1, int c2) const
00681 {
00682 //    it_assert1(c1>=0 && c2<no_cols && c1<=c2, "Mat<T>::get_cols: index out of range");
00683     Mat<T> m(no_rows, c2-c1+1);
00684 
00685     for (int i=0; i<m.cols(); i++)
00686       copy_vector(no_rows, data+(i+c1)*no_rows, m.data+i*m.no_rows);
00687     
00688     return m;
00689 }
00690 
00691 template<class T> inline
00692 Mat<T> Mat<T>::get_cols(const Vec<int> &indexlist) const
00693 {
00694   Mat<T> m(no_rows,indexlist.size());
00695 
00696   for (int i=0; i<indexlist.size(); i++) {
00697   //  it_assert1(indexlist(i)>=0 && indexlist(i)<no_cols, "Mat<T>::get_cols: index out of range");
00698     copy_vector(no_rows, data+indexlist(i)*no_rows, m.data+i*m.no_rows);
00699   }
00700 
00701   return m;
00702 }
00703 
00704 template<class T> inline
00705 void Mat<T>::set_row(int Index, const Vec<T> &v)
00706 {
00707  // it_assert1(Index>=0 && Index<no_rows, "Mat<T>::set_row: index out of range");
00708  // it_assert1(v.length() == no_cols, "Mat<T>::set_row: lengths doesn't match");
00709 
00710   copy_vector(v.size(), v._data(), 1, data+Index, no_rows);
00711 }
00712 
00713 template<class T> inline
00714 void Mat<T>::set_col(int Index, const Vec<T> &v)
00715 {
00716  // it_assert1(Index>=0 && Index<no_cols, "Mat<T>::set_col: index out of range");
00717  // it_assert1(v.length() == no_rows, "Mat<T>::set_col: lengths doesn't match");
00718 
00719   copy_vector(v.size(), v._data(), data+Index*no_rows);
00720 }
00721 
00722 template<class T> inline
00723 void Mat<T>::copy_row(int to, int from)
00724 {
00725  // it_assert1(to>=0 && from>=0 && to<no_rows && from<no_rows,
00726 //           "Mat<T>::copy_row: index out of range");
00727 
00728   if (from == to)
00729     return;
00730 
00731   copy_vector(no_cols, data+from, no_rows, data+to, no_rows);
00732 }
00733 
00734 template<class T> inline
00735 void Mat<T>::copy_col(int to, int from)
00736 {
00737 //  it_assert1(to>=0 && from>=0 && to<no_cols && from<no_cols,
00738 //           "Mat<T>::copy_col: index out of range");
00739 
00740   if (from == to)
00741     return;
00742 
00743   copy_vector(no_rows, data+from*no_rows, data+to*no_rows);
00744 }
00745 
00746 template<class T> inline
00747 void Mat<T>::swap_rows(int r1, int r2)
00748 {
00749  // it_assert1(r1>=0 && r2>=0 && r1<no_rows && r2<no_rows,
00750 //           "Mat<T>::swap_rows: index out of range");
00751 
00752   if (r1 == r2)
00753     return;
00754 
00755   swap_vector(no_cols, data+r1, no_rows, data+r2, no_rows);
00756 }
00757 
00758 template<class T> inline
00759 void Mat<T>::swap_cols(int c1, int c2)
00760 {
00761 //  it_assert1(c1>=0 && c2>=0 && c1<no_cols && c2<no_cols,
00762 //           "Mat<T>::swap_cols: index out of range");
00763 
00764   if (c1 == c2)
00765     return;
00766 
00767   swap_vector(no_rows, data+c1*no_rows, data+c2*no_rows);
00768 }
00769 
00770 template<class T> inline
00771 void Mat<T>::set_submatrix(int r1, int r2, int c1, int c2, const Mat<T> &m)
00772 {
00773 
00774   if (r1 == -1) r1 = no_rows-1;
00775   if (r2 == -1) r2 = no_rows-1;
00776   if (c1 == -1) c1 = no_cols-1;
00777   if (c2 == -1) c2 = no_cols-1;
00778 
00779  // it_assert1(r1>=0 && r2>=0 && r1<no_rows && r2<no_rows &&
00780  //            c1>=0 && c2>=0 && c1<no_cols && c2<no_cols, "Mat<T>::set_submatrix(): index out of range");
00781 
00782  // it_assert1(r2>=r1 && c2>=c1, "Mat<T>::set_submatrix: r2<r1 or c2<c1");
00783  // it_assert1(m.no_rows == r2-r1+1 && m.no_cols == c2-c1+1, "Mat<T>::set_submatrix(): sizes don't match");
00784 
00785   for (int i=0; i<m.no_cols; i++)
00786     copy_vector(m.no_rows, m.data+i*m.no_rows, data+(c1+i)*no_rows+r1);
00787 }
00788 
00789 template<class T> inline
00790 void Mat<T>::set_submatrix(int r1, int r2, int c1, int c2, const T t)
00791 {
00792 
00793   if (r1 == -1) r1 = no_rows-1;
00794   if (r2 == -1) r2 = no_rows-1;
00795   if (c1 == -1) c1 = no_cols-1;
00796   if (c2 == -1) c2 = no_cols-1;
00797 
00798   //  it_assert1(r1>=0 && r2>=0 && r1<no_rows && r2<no_rows &&
00799   //             c1>=0 && c2>=0 && c1<no_cols && c2<no_cols, "Mat<T>::set_submatrix(): index out of range");
00800 
00801   //  it_assert1(r2>=r1 && c2>=c1, "Mat<T>::set_submatrix: r2<r1 or c2<c1");
00802 
00803   int i, j, pos, rows = r2-r1+1;
00804 
00805   for (i=c1; i<=c2; i++) {
00806     pos = i*no_rows+r1;
00807     for (j=0; j<rows; j++) {
00808       data[pos++] = t;
00809     }
00810   }
00811 }
00812 
00813 template<class T>
00814 Mat<T> concat_horizontal(const Mat<T> &m1, const Mat<T> &m2)
00815 {
00816         //    it_assert1(m1.no_rows == m2.no_rows, "Mat<T>::concat_horizontal; wrong sizes");
00817 
00818     Mat<T> temp(m1.no_rows, m1.no_cols+m2.no_cols);
00819     int i;
00820   
00821     for (i=0; i<m1.no_cols; i++) {
00822         temp.set_col(i, m1.get_col(i));
00823     }
00824     for (i=0; i<m2.no_cols; i++) {
00825         temp.set_col(i+m1.no_cols, m2.get_col(i));
00826     }
00827 
00828     return temp;
00829 }
00830 
00831 template<class T>
00832 Mat<T> concat_vertical(const Mat<T> &m1, const Mat<T> &m2)
00833 {
00834         //    it_assert1(m1.no_cols == m2.no_cols, "Mat<T>::concat_vertical; wrong sizes");
00835   
00836     Mat<T> temp(m1.no_rows+m2.no_rows, m1.no_cols);
00837         int i;
00838   
00839     for (i=0; i<m1.no_rows; i++) {
00840         temp.set_row(i, m1.get_row(i));
00841     }
00842     for (i=0; i<m2.no_rows; i++) {
00843         temp.set_row(i+m1.no_rows, m2.get_row(i));
00844     }
00845 
00846     return temp;
00847 }
00848 
00849 template<class T> inline
00850 void Mat<T>::operator=(T t)
00851 {
00852   for (int i=0; i<datasize; i++)
00853     data[i] = t;
00854 }
00855 
00856 template<class T> inline
00857 void Mat<T>::operator=(const Mat<T> &m)
00858 {  
00859   set_size(m.no_rows,m.no_cols, false);
00860   if (m.datasize == 0) return;
00861 
00862   copy_vector(m.datasize, m.data, data);
00863 }
00864 
00865 template<class T> inline
00866 void Mat<T>::operator=(const Vec<T> &v)
00867 {
00868         //  it_assert1( (no_rows == 1 && no_cols == v.size()) || (no_cols == 1 && no_rows == v.size()),
00869         //            "Mat::op=(vec); wrong size");
00870 
00871  // construct a 1-d column of the vector
00872   set_size(v.size(), 1, false);
00873   set_col(0, v);
00874 }
00875 
00876 //-------------------- Templated friend functions --------------------------
00877 
00878 template<class T> inline
00879 void Mat<T>::operator+=(const Mat<T> &m)
00880 {
00881   if (datasize == 0)
00882     operator=(m);
00883   else {
00884     int i, j, m_pos=0, pos=0;
00885         //    it_assert1(m.no_rows==no_rows && m.no_cols==no_cols,"Mat<T>::operator+=: wrong sizes");
00886     for (i=0; i<no_cols; i++) {
00887       for (j=0; j<no_rows; j++)
00888         data[pos+j] += m.data[m_pos+j];
00889       pos += no_rows;
00890       m_pos += m.no_rows;
00891     }
00892   }
00893 }
00894 
00895 template<class T> inline
00896 Mat<T> operator+(const Mat<T> &m1, const Mat<T> &m2)
00897 {
00898     Mat<T> r(m1.no_rows, m1.no_cols);
00899     int i, j, m1_pos=0, m2_pos=0, r_pos=0;
00900 
00901         //    it_assert1(m1.no_rows==m2.no_rows && m1.no_cols == m2.no_cols, "Mat<T>::operator+: wrong sizes");
00902   
00903     for (i=0; i<r.no_cols; i++) {
00904         for (j=0; j<r.no_rows; j++)
00905             r.data[r_pos+j] = m1.data[m1_pos+j] + m2.data[m2_pos+j];
00906         // next column
00907         m1_pos += m1.no_rows;
00908         m2_pos += m2.no_rows;
00909         r_pos += r.no_rows;
00910     }
00911 
00912     return r;
00913 }
00914 
00915 template<class T> inline
00916 void Mat<T>::operator+=(T t)
00917 {  
00918     for (int i=0; i<datasize; i++)
00919       data[i] += t;
00920 }
00921 
00922 template<class T> inline
00923 Mat<T> operator+(const Mat<T> &m, T t)
00924 {
00925     Mat<T> r(m.no_rows, m.no_cols);
00926 
00927     for (int i=0; i<r.datasize; i++)
00928             r.data[i] = m.data[i] + t;
00929 
00930     return r;
00931 }
00932 
00933 template<class T> inline
00934 Mat<T> operator+(T t, const Mat<T> &m)
00935 {
00936     Mat<T> r(m.no_rows, m.no_cols);
00937 
00938     for (int i=0; i<r.datasize; i++)
00939             r.data[i] = t + m.data[i];
00940 
00941     return r;
00942 }
00943 
00944 template<class T> inline
00945 void Mat<T>::operator-=(const Mat<T> &m)
00946 {
00947     int i,j, m_pos=0, pos=0;
00948 
00949     if (datasize == 0) {
00950         set_size(m.no_rows, m.no_cols, false);
00951         for (i=0; i<no_cols; i++) {
00952             for (j=0; j<no_rows; j++)
00953                 data[pos+j] = -m.data[m_pos+j];
00954             // next column
00955             m_pos += m.no_rows;
00956             pos += no_rows;
00957         }
00958     } else {
00959                 //      it_assert1(m.no_rows==no_rows && m.no_cols==no_cols,"Mat<T>::operator-=: wrong sizes");
00960         for (i=0; i<no_cols; i++) {
00961             for (j=0; j<no_rows; j++)
00962                 data[pos+j] -= m.data[m_pos+j];
00963             // next column
00964             m_pos += m.no_rows;
00965             pos += no_rows;
00966         }
00967     }
00968 }
00969 
00970 template<class T> inline
00971 Mat<T> operator-(const Mat<T> &m1, const Mat<T> &m2)
00972 {
00973     Mat<T> r(m1.no_rows, m1.no_cols);
00974     int i, j, m1_pos=0, m2_pos=0, r_pos=0;
00975 
00976 //    it_assert1(m1.no_rows==m2.no_rows && m1.no_cols == m2.no_cols, "Mat<T>::operator-: wrong sizes");
00977   
00978     for (i=0; i<r.no_cols; i++) {
00979         for (j=0; j<r.no_rows; j++)
00980             r.data[r_pos+j] = m1.data[m1_pos+j] - m2.data[m2_pos+j];
00981         // next column
00982         m1_pos += m1.no_rows;
00983         m2_pos += m2.no_rows;
00984         r_pos += r.no_rows;
00985     }
00986 
00987     return r;
00988 }
00989 
00990 template<class T> inline
00991 void Mat<T>::operator-=(T t)
00992 {  
00993   for (int i=0; i<datasize; i++)
00994     data[i] -= t;
00995 }
00996 
00997 template<class T> inline
00998 Mat<T> operator-(const Mat<T> &m, T t)
00999 {
01000     Mat<T> r(m.no_rows, m.no_cols);
01001     int i, j, m_pos=0, r_pos=0;
01002 
01003     for (i=0; i<r.no_cols; i++) {
01004         for (j=0; j<r.no_rows; j++)
01005             r.data[r_pos+j] = m.data[m_pos+j] - t;
01006         // next column
01007         m_pos += m.no_rows;
01008         r_pos += r.no_rows;
01009     }
01010 
01011     return r;
01012 }
01013 
01014 template<class T> inline
01015 Mat<T> operator-(T t, const Mat<T> &m)
01016 {
01017     Mat<T> r(m.no_rows, m.no_cols);
01018     int i, j, m_pos=0, r_pos=0;
01019 
01020     for (i=0; i<r.no_cols; i++) {
01021         for (j=0; j<r.no_rows; j++)
01022             r.data[r_pos+j] = t - m.data[m_pos+j];
01023         // next column
01024         m_pos += m.no_rows;
01025         r_pos += r.no_rows;
01026     }
01027 
01028     return r;
01029 }
01030 
01031 
01032 template<class T> inline
01033 Mat<T> operator-(const Mat<T> &m)
01034 {
01035     Mat<T> r(m.no_rows, m.no_cols);
01036     int i, j, m_pos=0, r_pos=0;
01037 
01038     for (i=0; i<r.no_cols; i++) {
01039         for (j=0; j<r.no_rows; j++)
01040             r.data[r_pos+j] = -m.data[m_pos+j];
01041         // next column
01042         m_pos += m.no_rows;
01043         r_pos += r.no_rows;
01044     }
01045 
01046     return r;
01047 }
01048 
01049 // -------- Multiplication operator -------------
01050 
01051 #ifdef HAVE_CBLAS  // double and complex specializations using fast CBLAS routines
01052 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01053 #ifndef _MSC_VER
01054 template<>
01055 #endif
01056 void mat::operator*=(const mat &m)
01057 {
01058         //    it_assert1(no_cols == m.no_rows,"mat::operator*=: wrong sizes");
01059     mat r(no_rows, m.no_cols); // unnecessary memory??
01060 
01061     cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, no_rows, m.no_cols, no_cols, 1.0,
01062                           data, no_rows, m.data, m.no_rows, 0.0, r.data, r.no_rows);
01063 
01064     operator=(r); // time consuming
01065 }
01066 #ifndef _MSC_VER
01067 template<>
01068 #endif
01069 void cmat::operator*=(const cmat &m)
01070 {
01071         //    it_assert1(no_cols == m.no_rows,"cmat::operator*=: wrong sizes");
01072     double_complex alpha = double_complex(1.0), beta = double_complex(0.0);
01073     cmat r(no_rows, m.no_cols); // unnecessary memory??
01074 
01075     cblas_zgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, no_rows, m.no_cols, no_cols, (const void *)&alpha,
01076                 data, no_rows, m.data, m.no_rows, (const void*)&beta, &r.data, r.no_rows);
01077 
01078     operator=(r); // time consuming
01079 }
01080 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
01081 #endif /* HAVE_CBLAS */
01082 
01083 template<class T> inline
01084 void Mat<T>::operator*=(const Mat<T> &m)
01085 {
01086         //    it_assert1(no_cols == m.no_rows,"Mat<T>::operator*=: wrong sizes");
01087     Mat<T> r(no_rows, m.no_cols); // this consumes unnessesary memory
01088  
01089     T tmp;
01090   
01091     int i,j,k, r_pos=0, pos=0, m_pos=0;
01092   
01093     for (i=0; i<r.no_cols; i++) {
01094         for (j=0; j<r.no_rows; j++) {
01095             tmp = T(0);
01096             pos = 0;
01097             for (k=0; k<no_cols; k++) {
01098                 tmp += data[pos+j] * m.data[m_pos+k];
01099                 pos += no_rows;
01100             }
01101             r.data[r_pos+j] = tmp;
01102         }
01103         r_pos += r.no_rows;
01104         m_pos += m.no_rows;
01105     }
01106     operator=(r); // time consuming
01107 }
01108 
01109 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01110 #ifdef HAVE_CBLAS  // double and complex specializations using fast CBLAS routines
01111 #ifndef _MSC_VER
01112 template<>
01113 #endif
01114 mat operator*(const mat &m1, const mat &m2)
01115 {
01116         //    it_assert1(m1.no_cols == m2.no_rows,"mat::operator*: wrong sizes");
01117     mat r(m1.no_rows, m2.no_cols);
01118 
01119     cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, m1.no_rows, m2.no_cols, m1.no_cols, 1.0,
01120                 m1.data, m1.no_rows, m2.data, m2.no_rows, 0.0, r.data, r.no_rows);
01121     
01122     return r;
01123 }
01124 
01125 #ifndef _MSC_VER
01126 template<>
01127 #endif
01128 cmat operator*(const cmat &m1, const cmat &m2)
01129 {
01130         //    it_assert1(m1.no_cols == m2.no_rows,"cmat::operator*: wrong sizes");
01131     double_complex alpha = double_complex(1.0), beta = double_complex(0.0);
01132     cmat r(m1.no_rows, m2.no_cols);
01133 
01134     cblas_zgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, m1.no_rows, m2.no_cols, m1.no_cols, (const void *)&alpha,
01135                 m1.data, m1.no_rows, m2.data, m2.no_rows, (const void*)&beta, r.data, r.no_rows);
01136 
01137     return r;
01138 }
01139 #endif
01140 #endif //DOXYGEN_SHOULD_SKIP_THIS
01141 
01142 template<class T> inline
01143 Mat<T> operator*(const Mat<T> &m1, const Mat<T> &m2)
01144 {
01145         //    it_assert1(m1.no_cols == m2.no_rows,"Mat<T>::operator*: wrong sizes");
01146     Mat<T> r(m1.no_rows, m2.no_cols);
01147 
01148     T tmp;
01149     int i, j, k;
01150     T *tr=r.data, *t1, *t2=m2.data;
01151 
01152     for (i=0; i<r.no_cols; i++) {
01153         for (j=0; j<r.no_rows; j++) {
01154             tmp = T(0); t1 = m1.data+j;
01155             for (k=m1.no_cols; k>0; k--) {
01156                 tmp += *(t1) * *(t2++);
01157                 t1 += m1.no_rows;
01158             }
01159             *(tr++) = tmp; t2 -= m2.no_rows;
01160         }
01161         t2 += m2.no_rows;
01162     }
01163   
01164     return r;
01165 }
01166 
01167 template<class T> inline
01168 void Mat<T>::operator*=(T t)
01169 {    
01170   for (int i=0; i<datasize; i++)
01171     data[i] *= t;
01172 }
01173 
01174 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01175 #ifdef HAVE_CBLAS  // double and complex specializations using fast CBLAS routines
01176 #ifndef _MSC_VER
01177 template<>
01178 #endif
01179 vec operator*(const mat &m, const vec &v)
01180 {
01181         //    it_assert1(m.no_cols == v.size(),"mat::operator*: wrong sizes");
01182     vec r(m.no_rows);
01183   
01184     cblas_dgemv(CblasColMajor, CblasNoTrans, m.no_rows, m.no_cols, 1.0, m.data, m.no_rows, v._data(), 1,
01185                 0.0, r._data(), 1);
01186 
01187     return r;
01188 }
01189 
01190 #ifndef _MSC_VER
01191 template<>
01192 #endif
01193 cvec operator*(const cmat &m, const cvec &v)
01194 {
01195         //    it_assert1(m.no_cols == v.size(),"cmat::operator*: wrong sizes");
01196     double_complex alpha = double_complex(1.0), beta = double_complex(0.0);
01197     cvec r(m.no_rows);
01198 
01199     cblas_zgemv(CblasColMajor, CblasNoTrans, m.no_rows, m.no_cols, (const void *)&alpha, m.data, m.no_rows, 
01200                 v._data(), 1, (const void*)&beta, r._data(), 1);
01201 
01202     return r;
01203 }
01204 #endif
01205 #endif //DOXYGEN_SHOULD_SKIP_THIS
01206 
01207 template<class T> inline
01208 Vec<T> operator*(const Mat<T> &m, const Vec<T> &v)
01209 {
01210         //    it_assert1(m.no_cols == v.size(),"Mat<T>::operator*: wrong sizes");
01211     Vec<T> r(m.no_rows);
01212     int i, k, m_pos;
01213   
01214     for (i=0; i<m.no_rows; i++) {
01215         r(i) = T(0);
01216         m_pos = 0;
01217         for (k=0; k<m.no_cols; k++) {
01218             r(i) += m.data[m_pos+i] * v(k);
01219             m_pos += m.no_rows;
01220         }
01221     }
01222   
01223     return r;
01224 }
01225 
01226 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01227 #ifdef HAVE_CBLAS  // double and complex specializations using fast CBLAS routines
01228 #ifndef _MSC_VER
01229 template<>
01230 #endif //_MSC_VER
01231 vec operator*(const vec &v, const mat &m)
01232 {
01233         //    it_assert1(m.no_rows == v.size(),"Mat<T>::operator*: wrong sizes");
01234     vec r(m.no_cols);
01235   
01236     cblas_dgemv(CblasColMajor, CblasTrans, m.no_rows, m.no_cols, 1.0, m.data, m.no_rows, v._data(), 1,
01237                 0.0, r._data(), 1);
01238 
01239     return r;
01240 }
01241 
01242 #ifndef _MSC_VER
01243 template<>
01244 #endif //_MSC_VER
01245 cvec operator*(const cvec &v, const cmat &m)
01246 {
01247         //    it_assert1(m.no_rows == v.size(),"cmat::operator*: wrong sizes");
01248     double_complex alpha = double_complex(1.0), beta = double_complex(0.0);
01249     cvec r(m.no_cols);
01250   
01251     cblas_zgemv(CblasColMajor, CblasTrans, m.no_rows, m.no_cols, (const void *)&alpha, m.data, m.no_rows,
01252                 v._data(), 1, (const void*)&beta, r._data(), 1);
01253 
01254     return r;
01255 }
01256 #endif //HAVE_CBLAS
01257 #endif //DOXYGEN_SHOULD_SKIP_THIS
01258 
01259 template<class T> inline
01260 Vec<T> operator*(const Vec<T> &v, const Mat<T> &m)
01261 {
01262 //    it_assert1(m.no_rows == v.size(),"Mat<T>::operator*: wrong sizes");
01263     Vec<T> r(m.no_cols);
01264     int i, k, m_pos=0;
01265   
01266     for (i=0; i<m.no_cols; i++) {
01267         r(i) = T(0);
01268         for (k=0; k<m.no_rows; k++) {
01269             r(i) += m.data[m_pos+k] * v(k);
01270         }
01271         m_pos += m.no_rows;
01272     }
01273   
01274     return r;
01275 }
01276 
01277 
01278 template<class T> inline
01279 Mat<T> operator*(const Mat<T> &m, T t)
01280 {
01281   Mat<T> r(m.no_rows, m.no_cols);
01282 
01283   for (int i=0; i<r.datasize; i++)
01284     r.data[i] = m.data[i] * t;
01285 
01286   return r;
01287 }
01288 
01289 
01290 template<class T> inline
01291 Mat<T> operator*(T t, const Mat<T> &m)
01292 {
01293   Mat<T> r(m.no_rows, m.no_cols);
01294 
01295   for (int i=0; i<r.datasize; i++)
01296     r.data[i] = m.data[i] * t;
01297 
01298   return r;
01299 }
01300 
01301 
01302 template<class T> inline
01303 Mat<T> elem_mult(const Mat<T> &m1, const Mat<T> &m2)
01304 {
01305         //  it_assert1(m1.no_rows==m2.no_rows && m1.no_cols == m2.no_cols, "Mat<T>::elem_mult: wrong sizes");
01306   Mat<T> r(m1.no_rows, m1.no_cols);
01307   
01308   for (int i=0; i<r.datasize; i++)
01309     r.data[i] = m1.data[i] * m2.data[i];
01310 
01311     return r;
01312 }
01313 
01314 template<class T> inline
01315 void Mat<T>::operator/=(T t)
01316 {  
01317   for (int i=0; i<datasize; i++)
01318     data[i] /= t;
01319 }
01320 
01321 template<class T> inline
01322 Mat<T> operator/(const Mat<T> &m, T t)
01323 {
01324   Mat<T> r(m.no_rows, m.no_cols);
01325   
01326   for (int i=0; i<r.datasize; i++)
01327     r.data[i] = m.data[i] / t;
01328   
01329   return r;
01330 }
01331 
01332 template<class T> inline
01333 void Mat<T>::operator/=(const Mat<T> &m)
01334 {
01335         //  it_assert1(m.no_rows==no_rows && m.no_cols==no_cols, "Mat<T>::operator/=: wrong sizes");
01336   
01337   for (int i=0; i<datasize; i++)
01338     data[i] /= m.data[i];
01339 }
01340 
01341 template<class T> inline
01342 Mat<T> elem_div(const Mat<T> &m1, const Mat<T> &m2)
01343 {
01344         //    it_assert1(m1.no_rows==m2.no_rows && m1.no_cols == m2.no_cols, "Mat<T>::elem_div: worng sizes");
01345     Mat<T> r(m1.no_rows, m1.no_cols);
01346   
01347     for (int i=0; i<r.datasize; i++)
01348       r.data[i] = m1.data[i] / m2.data[i];
01349 
01350     return r;
01351 }
01352 
01353 template<class T>
01354 bool Mat<T>::operator==(const Mat<T> &m) const
01355 {
01356   if (no_rows!=m.no_rows || no_cols != m.no_cols) return false;
01357   for (int i=0;i<datasize;i++) {
01358     if (data[i]!=m.data[i]) return false;
01359   }
01360   return true;
01361 }
01362 
01363 
01364 template<class T>
01365 bool Mat<T>::operator!=(const Mat<T> &m) const
01366 {
01367     if (no_rows != m.no_rows || no_cols != m.no_cols) return true;
01368     for (int i=0;i<datasize;i++) {
01369         if (data[i]!=m.data[i]) return true;
01370     }
01371     return false;
01372 }
01373 
01374 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01375 #ifdef XXX
01376 template <class T>
01377 ostream &operator<<(ostream &os, const Mat<T> &m)
01378 {
01379     int i;
01380     
01381     switch (m.rows()) {
01382     case 0 :
01383         os << "[]";
01384         break;
01385     case 1 :
01386         os << '[' << m.get_row(0) << ']';
01387         break;
01388     default:
01389         os << '[' << m.get_row(0) << endl;
01390         for (i=1; i<m.rows()-1; i++)
01391             os << ' ' << m.get_row(i) << endl;
01392         os << ' ' << m.get_row(m.rows()-1) << ']';
01393     }
01394 
01395     return os;
01396 }
01397 
01398 template <class T>
01399 istream &operator>>(istream &is, Mat<T> &m)
01400 {
01401     string str, row;
01402     bool first_row=true;
01403 
01404     while (1) {
01405         getline(is, row);
01406         if (is.eof() || row.empty())
01407             break;
01408         if (!str.empty())
01409             str += ';';
01410         if (row[row.length()-1] == ']') {
01411             str += row.substr(0, row.length()-1);
01412             break;
01413         } 
01414         str += row;
01415         if (first_row && row.find(';') < row.length())
01416             break;
01417         first_row = false;
01418     }
01419     m.set(str);
01420 
01421     return is;
01422 }
01423 #endif
01424 #endif //DOXYGEN_SHOULD_SKIP_THIS
01425 
01426 
01427 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01428 
01429 template<class T>
01430 T sum(const Vec<T> &v)
01431 {
01432     T M=0;
01433     
01434     for (int i=0;i<v.length();i++)
01435         M+=v[i];
01436     
01437     return M;
01438 }
01439 
01440 /* T sum_sqr(const Vec<T> &v)
01441 */
01442 template<class T>
01443 T sum_sqr(const Vec<T> &v)
01444 {
01445     T M=0;
01446     
01447     for (int i=0; i<v.length(); i++)
01448         M += v[i] * v[i];
01449     
01450     return M;
01451 }
01452 
01453 template<class T>
01454 T max(const Vec<T> &in)
01455 {
01456     T   maxdata=in[0];
01457     for (int i=1;i<in.length();i++)
01458         if (in[i]>maxdata)
01459             maxdata=in[i];
01460     return maxdata;
01461 }
01462 
01463 template<class T>
01464 T min(const Vec<T> &in)
01465 {
01466     T mindata=in[0];
01467     for (int i=1;i<in.length();i++)
01468         if (in[i]<mindata)
01469             mindata=in[i];
01470     return mindata;
01471 }
01472 
01473 /*
01474   Return the postion of the maximum element in the vector
01475 */
01476 template<class T>
01477 int max_index(const Vec<T> &in)
01478 {
01479     int maxindex=0;
01480     for (int i=0;i<in.length();i++) 
01481         if (in[i]>in[maxindex])
01482             maxindex=i;
01483     return maxindex;
01484 }
01485 
01486 /*
01487   Return the postion of the minimum element in the vector
01488  */
01489 template<class T>
01490 int min_index(const Vec<T> &in)
01491 {
01492     int minindex=0;
01493     for (int i=0;i<in.length();i++)
01494         if (in[i]<in[minindex])
01495             minindex=i;
01496     return minindex;
01497 }
01498 
01499 /*
01500   Return the product of all elements in the vector
01501 */
01502 template<class T>
01503 T product(const Vec<T> &v)
01504 {
01505     double lnM=0;
01506     for (int i=0;i<v.length();i++)
01507         lnM += log(static_cast<double>(v[i]));
01508     return static_cast<T>(exp(lnM));
01509 }
01510 
01511 /*
01512   Vector cross product
01513 */
01514 template<class T>
01515 Vec<T> cross(const Vec<T> &v1, const Vec<T> &v2)
01516 {
01517     it_assert( v1.size() == 3 && v2.size() == 3, "cross: vectors should be of size 3");
01518 
01519     Vec<T> r(3);
01520 
01521     r(0) = v1(1) * v2(2) - v1(2) * v2(1);
01522     r(1) = v1(2) * v2(0) - v1(0) * v2(2);
01523     r(2) = v1(0) * v2(1) - v1(1) * v2(0);
01524     
01525     return r;
01526 }
01527 
01528 template<class T>
01529 double geometric_mean(const Vec<T> &v)
01530 {
01531     return exp(log(product(v))/v.length());
01532 }
01533 
01534 /*
01535   Return the median value of the elements in the vector
01536 */
01537 template<class T>
01538 double median(const Vec<T> &v)
01539 {
01540     Vec<T> invect(v);
01541     sort(invect);
01542     return (double)(invect[(invect.length()-1)/2]+invect[invect.length()/2])/2.0;
01543 }
01544 
01545 
01546 //  Inefficient, but correct version:
01547 /*
01548 template<class T>
01549 double variance(const Vec<T> &v) {
01550     int         len = v.length();
01551     return (double)(pow((double)norm(v,2),2)-pow((double)abs(mean(v)),2)*len)/(len-1);
01552 }
01553 */
01554 /*
01555   Calculate the 2-norm: norm(v)=sqrt(sum(abs(v).^2))
01556 */
01557 template<class T>
01558 double norm(const Vec<T> &v)
01559 {
01560     int i;
01561     double e=0.0;
01562     
01563     for (i=0; i<v.length(); i++)
01564                 e += SQR( v[i] );
01565 
01566     return sqrt(e);
01567 }
01568 /*
01569 template< > double norm(const cvec &v)
01570 {
01571     int i;
01572     double e=0.0;
01573     
01574     for (i=0; i<v.length(); i++)
01575         e += std::norm(v[i]);
01576 
01577     return sqrt(e);
01578 }
01579 */
01580 /*
01581   Calculate the p-norm: norm(v,p)=sum(abs(v).^2)^(1/p)
01582 */
01583 template<class T>
01584 double norm(const Vec<T> &v, int p)
01585 {
01586     int i;
01587     double e=0;
01588     
01589     for (i=0;i<v.length();i++)
01590         e+=pow(fabs(v[i]),(double)p); // fabs() shoud be OK
01591 
01592     return pow(e,1.0/(double)p);
01593 }
01594 /*
01595 template<double_complex>
01596 double norm(const Vec<double_complex> &v, int p)
01597 {
01598     int i;
01599     double e=0;
01600     
01601     for (i=0;i<v.length();i++)
01602         e+=pow(std::norm(v[i]), p/2.0); // Yes, 2.0 is correct!
01603 
01604     return pow(e,1.0/(double)p);
01605 }
01606 */
01607 /*
01608   Return the variance of the elements in the vector. Normalized with N-1 to be unbiased.
01609  */
01610 template<class T>
01611 double variance(const Vec<T> &v)
01612 {
01613     int len = v.length();
01614     const T *p=v._data();
01615     T sum=0.0;
01616         T sq_sum=0.0;
01617 
01618     for (int i=0; i<len; i++, p++) {
01619                 sum += *p;
01620                 sq_sum += SQR(*p * *p);
01621     }
01622     
01623     return (double)(sq_sum - SQR(sum)/len) / (len-1);
01624 }
01625 
01626 
01627 /*
01628   Calculate the energy: squared 2-norm. energy(v)=sum(v.^2)
01629 */
01630 template<class T>
01631 double energy(const Vec<T> &v)
01632 {
01633     return SQR(norm(v));
01634 }
01635 
01636 /* 
01637 template<class T>
01638 Vec<T> normalize(Vec<T> &v1, T radius) {
01639   dvec temp(v1.length());
01640   int i;
01641   T e=norm(v1),r;
01642   if (e!=0) {
01643     r=radius/e;
01644     for (i=0;i<v1.length();i++) {
01645       v1[i]*=r;
01646     }
01647   }
01648   return temp;
01649 }
01650 */
01651 
01652 /*
01653   Reverse the input vector
01654 */
01655 template<class T>
01656 Vec<T> reverse(const Vec<T> &in)
01657 {
01658     int i, s=in.length();
01659   
01660     Vec<T> out(s);
01661     for (i=0;i<s;i++)
01662         out[i]=in[s-1-i];
01663     return out;
01664 }
01665 
01666 /*
01667   Repeat each element in the vector norepeats times in sequence
01668 */
01669 template<class T>
01670 Vec<T> repeat(const Vec<T> &v, int norepeats)
01671 {
01672     Vec<T> temp(v.length()*norepeats);
01673   
01674     for(int i=0;i<v.length();i++) {
01675         for(int j=0;j<norepeats;j++)
01676             temp(i*norepeats+j)=v(i);
01677     }
01678     return temp;
01679 }
01680 
01681 /*
01682   Apply arbitrary function to a vector
01683  */
01684 template<class T, class fT>
01685 Vec<T> apply_function(fT (*f)(fT), const Vec<T> &data)
01686 {
01687     Vec<T> out(data.length());
01688   
01689     for (int i=0;i<data.length();i++) 
01690         out[i]=static_cast<T>(f(static_cast<fT>(data[i])));
01691     return out;
01692 }
01693 
01694 /*
01695 This is probably som old code that should be removed.
01696 Commented out by Pål Frenger 2003-01-15
01697 
01698 template <class T>
01699 void insertion_sort(Vec<T> &v)
01700 {
01701     if (v.size() < 2)
01702         return;
01703     
01704     if (v[1] < v[0])
01705         swap(v[0], v[1]);
01706         
01707     for (int i=2; i<v.size(); i++) {
01708         if (v[i] < v[i-1]) {
01709             T tmp = v[i];
01710             v[i] = v[i-1];
01711             j = i-2;
01712             while (j>0 && tmp<v[j]) {
01713                 v[j+1] = v[j];
01714                 j--;
01715             }
01716             v[j] = tmp;
01717         }
01718     }
01719 }
01720 */
01721 
01722 template<class T> void QS(int low, int high, Vec<T> &data) {
01723     int plow, phigh;
01724     T a,test;
01725         
01726     if (high>low) {
01727         a=data[low];
01728         plow=low;
01729         phigh=high;
01730         test=data[phigh];
01731         while (plow<phigh) {
01732             if (test<a) {
01733                 data[plow]=test;
01734                 plow++;
01735                 test=data[plow];
01736             } else {
01737                 data[phigh]=test;
01738                 phigh--;
01739                 test=data[phigh];
01740             }
01741         }
01742         data[plow]=a;
01743         QS(low,plow-1,data);
01744         QS(plow+1,high,data);
01745     }
01746 }
01747 
01748 // Instantiation of help functions
01749 template void QS(int low, int high, vec &data);
01750 template void QS(int low, int high, svec &data);
01751 template void QS(int low, int high, ivec &data);
01752 template void QS(int low, int high, bvec &data);
01753 
01754 /*
01755   Sort the the vector in increasing order
01756 */
01757 template<class T>
01758 void sort(Vec<T> &data)
01759 {
01760     QS(0,data.size()-1,data);
01761 }
01762 
01763 template<class T>
01764 void QSindex(int low, int high, ivec &indexlist, const Vec<T> &data)
01765 {
01766     int plow,phigh,testindex,aindex;
01767     T a,test;
01768 
01769     if (high>low) {
01770         aindex=indexlist[low];
01771         a=data[aindex];
01772         plow=low;
01773         phigh=high;
01774         testindex=indexlist[phigh];
01775         test=data[testindex];
01776         while (plow<phigh) {
01777             if (test<a) {
01778                 indexlist[plow]=testindex;
01779                 plow++;
01780                 testindex=indexlist[plow];
01781                 test=data[testindex];
01782             } else {
01783                 indexlist[phigh]=testindex;
01784                 phigh--;
01785                 testindex=indexlist[phigh];
01786                 test=data[testindex];
01787             }
01788         }
01789         indexlist[plow]=aindex;
01790         QSindex(low,plow-1,indexlist,data);
01791         QSindex(plow+1,high,indexlist,data);
01792     }
01793 }
01794 
01795 // Instantiation of help functions
01796 template void QSindex(int low, int high, ivec &indexlist, const vec &data);
01797 template void QSindex(int low, int high, ivec &indexlist, const svec &data);
01798 template void QSindex(int low, int high, ivec &indexlist, const ivec &data);
01799 template void QSindex(int low, int high, ivec &indexlist, const bvec &data);
01800 
01801 /*
01802   Return an index vector corresponding to a sorted vector (increasing order)
01803 */
01804 template<class T>
01805 ivec sort_index(const Vec<T> &data)
01806 {
01807     int N=data.length(),i;
01808     ivec indexlist(N);
01809   
01810     for(i=0;i<N;i++) {
01811         indexlist(i)=i;
01812     }
01813     QSindex(0,N-1,indexlist,data);
01814     return indexlist;
01815 }
01816 
01817 /*
01818   Zero-pad a vector to size n
01819  */
01820 template<class T>
01821 Vec<T> zero_pad(const Vec<T> &v, int n)
01822 {
01823     it_assert(n>=v.size(), "zero_pad() cannot shrink the vector!");
01824     Vec<T> v2(n);
01825     v2.set_subvector(0, v.size()-1, v);
01826     if (n > v.size())
01827         v2.set_subvector(v.size(), n-1, T(0));
01828 
01829     return v2;
01830 }
01831 
01832 /*
01833   Zero-pad a vector to the nearest greater power of two
01834  */
01835 template<class T>
01836 Vec<T> zero_pad(const Vec<T> &v)
01837 {
01838     int n = pow2(needed_bits(v.size()));
01839     
01840     return n==v.size() ? v : zero_pad(v, n);
01841 }
01842 
01843 /*
01844   Zero-pad a matrix to size rows x cols
01845  */
01846 template<class T>
01847 Mat<T> zero_pad(const Mat<T> &m, int rows, int cols)
01848 {
01849     it_assert(rows>=m.rows() && cols>=m.cols(), "zero_pad() cannot shrink the matrix!");
01850     Mat<T> m2(rows, cols);
01851     m2.set_submatrix(0,m.rows()-1,0,m.cols()-1, m);
01852     if (cols > m.cols()) // Zero
01853         m2.set_submatrix(0,m.rows()-1, m.cols(),cols-1, T(0));
01854     if (rows > m.rows()) // Zero
01855         m2.set_submatrix(m.rows(), rows-1, 0, cols-1, T(0));
01856 
01857     return m2;
01858 }
01859 //---------- Template functions for Mat<T> ----------------------
01860 
01861 /*
01862   Sum of elements in a matrix
01863 */
01864 template<class T>
01865 T sum(const Mat<T> &v)
01866 {
01867     int i, j;
01868     T M=0;
01869     
01870     for (i=0; i<v.rows(); i++)
01871         for (j=0; j<v.cols(); j++)
01872             M += v(i,j);
01873     
01874     return M;
01875 }
01876 
01877 /*
01878   Sum of square of the elements in a matrix
01879 */
01880 template<class T>
01881 T sum_sqr(const Mat<T> &v)
01882 {
01883     int i, j;
01884     T M=0;
01885     
01886     for (i=0; i<v.rows(); i++)
01887         for (j=0; j<v.cols(); j++)
01888             M += v(i,j) * v(i,j);
01889     
01890     return M;
01891 }
01892 
01893 /*
01894   Return the maximum element in the vector
01895 */
01896 template<class T>
01897 T max(const Mat<T> &m)
01898 {
01899     T maxdata = m(0,0);
01900     int i, j;
01901         
01902     for (i=0; i<m.rows(); i++)
01903         for (j=0; j<m.cols(); j++)
01904             if (m(i,j) > maxdata)
01905                 maxdata = m(i,j);
01906         
01907     return maxdata;
01908 }
01909 
01910 /*
01911   Return the minimum element in the vector
01912 */
01913 template<class T>
01914 T min(const Mat<T> &m)
01915 {
01916     T mindata = m(0,0);
01917     int i, j;
01918         
01919     for (i=0; i<m.rows(); i++)
01920         for (j=0; j<m.cols(); j++)
01921             if (m(i,j) < mindata)
01922                 mindata = m(i,j);
01923         
01924     return mindata;
01925 }
01926 
01927 /*
01928   Return the postion of the maximum element in the matrix
01929 */
01930 template<class T>
01931 void max_index(const Mat<T> &m, int &row, int &col)
01932 {
01933     T maxdata = m(0,0);
01934     int i, j;
01935 
01936     row = col = 0;
01937     for (i=0; i<m.rows(); i++)
01938         for (j=0; j<m.cols(); j++)
01939             if (m(i,j) > maxdata) {
01940                 row = i;
01941                 col = j;
01942                 maxdata = m(i,j);
01943             }
01944 }
01945 
01946 /*
01947   Return the postion of the minimum element in the matrix
01948 */
01949 template<class T>
01950 void min_index(const Mat<T> &m, int &row, int &col)
01951 {
01952     T mindata = m(0,0);
01953     int i, j;
01954         
01955     row = col = 0;
01956     for (i=0; i<m.rows(); i++)
01957         for (j=0; j<m.cols(); j++)
01958             if (m(i,j) < mindata) {
01959                 row = i;
01960                 col = j;
01961                 mindata = m(i,j);
01962             }
01963 }
01964 
01965 /*
01966   Return the product of all elements in the matrix
01967 */
01968 template<class T>
01969 T product(const Mat<T> &m)
01970 {
01971     int i, j;
01972     double lnM=0;
01973     
01974     for (i=0; i<m.rows(); i++)
01975         for (j=0; j<m.cols(); j++)
01976             lnM += log(m(i,j));
01977     
01978     return static_cast<T>(exp(lnM));
01979 }
01980 /*
01981   Return a diagonal matrix
01982 */
01983 template<class T>
01984 Mat<T> diag(const Vec<T> &in)
01985 {
01986     Mat<T> m(in.size(), in.size());
01987     m = T(0);
01988     for (int i=in.size()-1; i>=0; i--)
01989         m(i,i) = in(i);
01990     return m;
01991 }
01992 
01993 template<class T>
01994 void diag(const Vec<T> &in, Mat<T> &m)
01995 {
01996     m.set_size(in.size(), in.size(), false);
01997     m = T(0);
01998     for (int i=in.size()-1; i>=0; i--)
01999         m(i,i) = in(i);
02000 }
02001 
02002 /*
02003   Return the diagonal of a matrix
02004 */
02005 template<class T>
02006 Vec<T> diag(const Mat<T> &in)
02007 {
02008     Vec<T> t(std::min(in.rows(), in.cols()));
02009 
02010     for (int i=0; i<t.size(); i++)
02011         t(i) = in(i,i);
02012 
02013     return t;
02014 }
02015 
02016 
02017 template<class T>
02018 Mat<T> bidiag(const Vec<T> &main, const Vec<T> &sup)
02019 {
02020     it_assert(main.size() == sup.size()+1, "bidiag()");
02021     
02022     int n=main.size();
02023     Mat<T> m(n, n);
02024     m = T(0);
02025     for (int i=0; i<n-1; i++) {
02026         m(i,i) = main(i);
02027         m(i,i+1) = sup(i);
02028     }
02029     m(n-1,n-1) = main(n-1);
02030     
02031     return m;
02032 }
02033 
02034 template<class T>
02035 void   bidiag(const Vec<T> &main, const Vec<T> &sup, Mat<T> &m)
02036 {
02037     it_assert(main.size() == sup.size()+1, "bidiag()");
02038     
02039     int n=main.size();
02040     m.set_size(n, n);
02041     m = T(0);
02042     for (int i=0; i<n-1; i++) {
02043         m(i,i) = main(i);
02044         m(i,i+1) = sup(i);
02045     }
02046     m(n-1,n-1) = main(n-1);
02047 }
02048 
02049 template<class T>
02050 void bidiag(const Mat<T> &m, Vec<T> &main, Vec<T> &sup)
02051 {
02052     it_assert(m.rows() == m.cols(), "bidiag(): Matrix must be square!");
02053     
02054     int n=m.cols();
02055     main.set_size(n);
02056     sup.set_size(n-1);
02057     for (int i=0; i<n-1; i++) {
02058         main(i) = m(i,i);
02059         sup(i) = m(i,i+1);
02060     }
02061     main(n-1) = m(n-1,n-1);
02062 }
02063 
02064 
02065 template<class T>
02066 Mat<T> tridiag(const Vec<T> &main, const Vec<T> &sup, const Vec<T> &sub)
02067 {
02068     it_assert(main.size()==sup.size()+1 && main.size()==sub.size()+1, "bidiag()");
02069     
02070     int n=main.size();
02071     Mat<T> m(n, n);
02072     m = T(0);
02073     for (int i=0; i<n-1; i++) {
02074         m(i,i) = main(i);
02075         m(i,i+1) = sup(i);
02076         m(i+1,i) = sub(i);
02077     }
02078     m(n-1,n-1) = main(n-1);
02079     
02080     return m;
02081 }
02082 
02083 template<class T>
02084 void tridiag(const Vec<T> &main, const Vec<T> &sup, const Vec<T> &sub, Mat<T> &m)
02085 {
02086     it_assert(main.size()==sup.size()+1 && main.size()==sub.size()+1, "bidiag()");
02087     
02088     int n=main.size();
02089     m.set_size(n, n);
02090     m = T(0);
02091     for (int i=0; i<n-1; i++) {
02092         m(i,i) = main(i);
02093         m(i,i+1) = sup(i);
02094         m(i+1,i) = sub(i);
02095     }
02096     m(n-1,n-1) = main(n-1);
02097 }
02098 
02099 template<class T>
02100 void tridiag(const Mat<T> &m, Vec<T> &main, Vec<T> &sup, Vec<T> &sub)
02101 {
02102     it_assert(m.rows() == m.cols(), "tridiag(): Matrix must be square!");
02103     
02104     int n=m.cols();
02105     main.set_size(n);
02106     sup.set_size(n-1);
02107     sub.set_size(n-1);
02108     for (int i=0; i<n-1; i++) {
02109         main(i) = m(i,i);
02110         sup(i) = m(i,i+1);
02111         sub(i) = m(i+1,i);
02112     }
02113     main(n-1) = m(n-1,n-1);
02114 }
02115 
02116 /*
02117   Calculate the trace of a matrix
02118  */
02119 template<class T>
02120 T trace(const Mat<T> &in)
02121 {
02122     return sum(diag(in));
02123 }
02124 
02125 /*
02126   Transpose of a matrix
02127 */
02128 template<class T>
02129 void transpose(const Mat<T> &m, Mat<T> &out)
02130 {
02131   out.set_size(m.cols(),m.rows(), false);
02132   
02133   for (int i=0; i<m.rows(); i++) {
02134     for (int j=0; j<m.cols(); j++) {
02135       out(j,i) = m(i,j);
02136     }
02137   }
02138 }
02139 
02140 /*
02141   Transpose of a matrix
02142 */
02143 template<class T>
02144 Mat<T> transpose(const Mat<T> &m)
02145 {
02146   Mat<T> temp(m.cols(),m.rows());
02147   
02148   for (int i=0; i<m.rows(); i++) {
02149     for (int j=0; j<m.cols(); j++) {
02150       temp(j,i) = m(i,j);
02151     }
02152   }
02153   return temp;
02154 }
02155 
02156 /*
02157   Repeats each column norepeats times in sequence.
02158 */
02159 template<class T>
02160 Mat<T> repeat(const Mat<T> &v, int norepeats)
02161 {
02162     Mat<T> temp(v.rows(),v.cols()*norepeats);
02163     for (int j=0;j<v.cols();j++) {
02164         for (int i=0;i<norepeats;i++) {
02165             temp.set_col(j*norepeats+i,v.get_col(j));
02166         }
02167     }
02168     return temp;
02169 }
02170 
02171 /*
02172  */
02173 template<class T, class fT>
02174 Mat<T> apply_function(fT (*f)(fT), const Mat<T> &data)
02175 {
02176     Mat<T> out(data.rows(),data.cols());
02177 
02178     for (int i=0;i<out.rows();i++)
02179         for (int j=0;j<out.cols();j++)
02180             out(i,j)=static_cast<T>(f(static_cast<fT>(data(i,j))));
02181 
02182     return out;
02183 }
02184 
02185 
02186 #define absolut(x) (((x)>0) ? (x) : (-(x)))
02187 
02188 
02189 /*
02190   Row vectorize the matrix [(0,0) (0,1) ... (N-1,N-2) (N-1,N-1)]
02191 */
02192 template<class T>
02193 Vec<T> rvectorize(const Mat<T> &m)
02194 {
02195     int i, j, n=0, r=m.rows(), c=m.cols();
02196     Vec<T> v(r * c);
02197     
02198     for (i=0; i<r; i++)
02199         for (j=0; j<c; j++)
02200             v(n++) = m(i,j);
02201 
02202     return v;
02203 }
02204 
02205 
02206 /*
02207   Column vectorize the matrix [(0,0) (1,0) ... (N-2,N-1) (N-1,N-1)]
02208 */
02209 template<class T>
02210 Vec<T> cvectorize(const Mat<T> &m)
02211 {
02212     int i, j, n=0, r=m.rows(), c=m.cols();
02213     Vec<T> v(r * c);
02214     
02215     for (j=0; j<c; j++)
02216         for (i=0; i<r; i++)
02217             v(n++) = m(i,j);
02218 
02219     return v;
02220 }
02221 
02222 
02223 /*
02224   Reshape the matrix into an rows*cols matrix taken columnwise from the original matrix
02225 */
02226 template<class T>
02227 Mat<T> reshape(const Mat<T> &m, int rows, int cols)
02228 {
02229   it_assert1(m.rows()*m.cols() == rows*cols, "Mat<T>::reshape: Sizes must match");
02230   Mat<T> temp(rows, cols);
02231   int i, j, ii=0, jj=0;
02232   for (j=0; j<m.cols(); j++) {
02233     for (i=0; i<m.rows(); i++) {
02234       temp(ii++,jj) = m(i,j);
02235       if (ii == rows) {
02236         jj++; ii=0;
02237       }
02238     }
02239   }
02240   return temp;
02241 }
02242 
02243 /*
02244   Reshape the vector into an rows*cols matrix writing into new matrix columnwise
02245 */
02246 template<class T>
02247 Mat<T> reshape(const Vec<T> &v, int rows, int cols)
02248 {
02249         //  it_assert1(v.size() == rows*cols, "Mat<T>::reshape: Sizes must match");
02250   Mat<T> temp(rows, cols);
02251   int i, j, ii=0;
02252   for (j=0; j<cols; j++) {
02253     for (i=0; i<rows; i++) {
02254       temp(i,j) = v(ii++);
02255     }
02256   }
02257   return temp;
02258 }
02259 
02260 
02261 
02262 /*
02263   Upsample a vector by incerting \a (usf-1) zeros after each sample
02264 */
02265 template<class T>
02266 void upsample(const Vec<T> &v, int usf, Vec<T> &u)
02267 {
02268         //  it_assert1(usf >= 1, "upsample: upsampling factor must be equal or greater than one" );
02269   u.set_size(v.length()*usf);
02270   u.clear();
02271   for(long i=0;i<v.length();i++)
02272     u(i*usf)=v(i); 
02273 }
02274 
02275 
02276 template<class T>
02277 Vec<T> upsample(const Vec<T> &v, int usf)
02278 {
02279   Vec<T> u;
02280   upsample(v,usf,u);
02281   return u;  
02282 }
02283 
02284 /*
02285   Upsample each column by incerting \a (usf-1) zeros after each column
02286 */
02287 template<class T>
02288 void upsample(const Mat<T> &v, int usf, Mat<T> &u)
02289 {
02290         //  it_assert1(usf >= 1, "upsample: upsampling factor must be equal or greater than one" );
02291   u.set_size(v.rows(),v.cols()*usf);
02292   u.clear();
02293   for (long j=0;j<v.cols();j++)
02294     u.set_col(j*usf,v.get_col(j));
02295 }
02296 
02297 template<class T>
02298 Mat<T> upsample(const Mat<T> &v, int usf)
02299 {
02300   Mat<T> u;
02301   upsample(v,usf,u);
02302   return u;  
02303 }
02304 
02305 /*
02306   Upsample each column by a factor of  \a (usf-1) by linear interpolation
02307 */
02308 template<class T>
02309 void lininterp(const Mat<T> &v, int usf, Mat<T> &u)
02310 {
02311         //  it_assert1(usf >= 1, "lininterp: upsampling factor must be equal or greater than one" );
02312   long L = (v.cols()-1)*usf+1;
02313   u.set_size(v.rows(),L);
02314   for (long i = 0; i < v.rows(); i++){ 
02315     for (long j = 0; j < L-1; j++)
02316       //u(i,j) = (v(i,j/usf) + (j % usf)/((float)usf)*(v(i,(j+usf)/usf)-v(i,j/usf)));  
02317       u(i,j) = (v(i,j/usf) + (j % usf)/((double)usf)*(v(i,(j+usf)/usf)-v(i,j/usf)));  
02318     u(i,L-1) = v(i,v.cols()-1);
02319   }
02320 }
02321 
02322 /*
02323   Upsample each column by a factor of  \a (usf-1) by linear interpolation
02324 */
02325 template<class T>
02326 Mat<T> lininterp(const Mat<T> &v, int usf)
02327 {
02328   Mat<T> u;
02329   upsample(v,usf,u);
02330   return u;  
02331 }
02332 
02333 
02334 /*
02335   Upsample by a factor of  \a (usf-1) by linear interpolation
02336 */
02337 template<class T>
02338 void lininterp(const Vec<T> &v, int usf, Vec<T> &u)
02339 {
02340         //  it_assert1(usf >= 1, "lininterp: upsampling factor must be equal or greater than one" );
02341   long L = (v.length()-1)*usf+1;
02342   u.set_size(L);
02343   for (long j = 0; j < L-1; j++) {
02344     //u(j) = (v(j/usf) + (j % usf)/((float)usf)*(v((j+usf)/usf)-v(j/usf)));  
02345     u(j) = (v(j/usf) + (j % usf)/((double)usf)*(v((j+usf)/usf)-v(j/usf)));  
02346   }
02347   u(L-1) = v(v.length()-1);
02348 }
02349 
02350 
02351 /*
02352   Upsample by a factor of  \a (usf-1) by linear interpolation
02353 */
02354 template<class T>
02355 Vec<T> lininterp(const Vec<T> &v, int usf)
02356 {
02357   Vec<T> u;
02358   upsample(v,usf,u);
02359   return u;  
02360 }
02361 
02362 
02363 #endif //DOXYGEN_SHOULD_SKIP_THIS
02364 }
02365 #endif
02366  

Generated on Fri Sep 16 11:02:29 2005 for spuc by  doxygen 1.4.4