root/win32/itpp-4.0.1/itpp/base/smat.h @ 47

Revision 35, 30.4 kB (checked in by mido, 17 years ago)

zasadni zmeny ve /win32

Line 
1/*!
2 * \file
3 * \brief Sparse Matrix Class Definitions
4 * \author Tony Ottosson and Tobias Ringstrom
5 *
6 * -------------------------------------------------------------------------
7 *
8 * IT++ - C++ library of mathematical, signal processing, speech processing,
9 *        and communications classes and functions
10 *
11 * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 *
27 * -------------------------------------------------------------------------
28 */
29
30#ifndef SMAT_H
31#define SMAT_H
32
33#ifndef _MSC_VER
34#  include <itpp/config.h>
35#else
36#  include <itpp/config_msvc.h>
37#endif
38
39#include <itpp/base/svec.h>
40
41
42namespace itpp {
43
44  // Declaration of class Vec
45  template <class T> class Vec;
46  // Declaration of class Mat
47  template <class T> class Mat;
48  // Declaration of class Sparse_Vec
49  template <class T> class Sparse_Vec;
50  // Declaration of class Sparse_Mat
51  template <class T> class Sparse_Mat;
52
53  // ------------------------ Sparse_Mat Friends -------------------------------------
54
55  //! m1+m2 where m1 and m2 are sparse matrices
56  template <class T>
57    Sparse_Mat<T> operator+(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
58
59  //! c*m where c is a scalar and m is a sparse matrix
60  template <class T>
61    Sparse_Mat<T> operator*(const T &c, const Sparse_Mat<T> &m);
62
63  //! m1*m2 where m1 and m2 are sparse matrices
64  template <class T>
65    Sparse_Mat<T> operator*(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
66
67  //! m*v where m is a sparse matrix and v is a sparse vector
68  template <class T>
69    Sparse_Vec<T> operator*(const Sparse_Mat<T> &m, const Sparse_Vec<T> &v);
70
71  //! m*v where m is a sparse matrix and v is a full column vector
72  template <class T>
73    Vec<T> operator*(const Sparse_Mat<T> &m, const Vec<T> &v);
74
75  //! v'*m where m is a sparse matrix and v is a full column vector
76  template <class T>
77    Vec<T> operator*(const Vec<T> &v, const Sparse_Mat<T> &m);
78
79  //! m'*m where m is a sparse matrix
80  template <class T>
81    Mat<T> trans_mult(const Sparse_Mat<T> &m);
82
83  //! m'*m where m is a sparse matrix
84  template <class T>
85    Sparse_Mat<T> trans_mult_s(const Sparse_Mat<T> &m);
86
87  //! m1'*m2 where m1 and m2 are sparse matrices
88  template <class T>
89    Sparse_Mat<T> trans_mult(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
90
91  //! m'*v where m is a sparse matrix and v is a full column vector
92  template <class T>
93    Vec<T> trans_mult(const Sparse_Mat<T> &m, const Vec<T> &v);
94
95  //! m1*m2' where m1 and m2 are sparse matrices
96  template <class T>
97    Sparse_Mat<T> mult_trans(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
98
99  /*!
100    \brief Templated Sparse Matrix Class
101    \author Tony Ottosson and Tobias Ringstrom
102
103    A sparse matrix is a matrix where most elements are zero. The
104    maximum number of non-zero elements in each column is a parameter
105    to the constructor.
106
107    The implementation is based on representing all columns as sparse
108    vectors. Thus, column access generally is much faster than row
109    access. The elements in each vector are stored in random order,
110    i.e. they are not sorted.
111  */
112  template <class T>
113    class Sparse_Mat {
114    public:
115
116    //! Default constructor
117    Sparse_Mat();
118
119    /*!
120      \brief Initiate an empty sparse matrix
121
122      A Sparse_Mat consists of colums that have the type Sparse_Vec. The maximum number of non-zero elements is each column
123      is denoted \c row_data_init.
124
125      \param rows Number of rows in the matrix
126      \param cols Number of columns in the matrix
127      \param row_data_init The maximum number of non-zero elements in each column (default value is 200)
128    */
129    Sparse_Mat(int rows, int cols, int row_data_init=200);
130
131    //! Initiate a new sparse matrix. The elements of \c m are copied into the new sparse matrix
132    Sparse_Mat(const Sparse_Mat<T> &m);
133
134    //! Initiate a new sparse matrix from a dense matrix. The elements of \c m are copied into the new sparse matrix
135    Sparse_Mat(const Mat<T> &m);
136
137    /*!
138      \brief Initiate a new sparse matrix from a dense matrix. Elements of \c m larger than \c epsilon are copied into the new sparse matrix.
139
140      \note If the type T is double complex, then the elements of \c m larger than \c abs(epsilon) are copied into the new sparse matrix.
141    */
142    Sparse_Mat(const Mat<T> &m, T epsilon);
143
144    //! Destructor
145    ~Sparse_Mat();
146
147    /*!
148      \brief Set the size of the sparse matrix
149
150      A Sparse_Mat consists of colums that have the type Sparse_Vec. The maximum number of non-zero elements is each column
151      is denoted \c row_data_init, with default value =-1 indicating that the number of data elements is not changed.
152
153      \param rows Number of rows in the matrix
154      \param cols Number of columns in the matrix
155      \param row_data_init The maximum number of non-zero elements in each column (default value -1 \c => allocated size for the data is not changed)
156    */
157    void set_size(int rows, int cols, int row_data_init=-1);
158
159    //! Returns the number of rows of the sparse matrix
160    int rows() const { return n_rows; }
161
162    //! Returns the number of columns of the sparse matrix
163    int cols() const { return n_cols; }
164
165    //! The number of non-zero elements in the sparse matrix
166    int nnz();
167
168    //! Returns the density of the sparse matrix: (number of non-zero elements)/(total number of elements)
169    double density();
170
171    //! Set the maximum number of non-zero elements in each column equal to the actual number of non-zero elements in each column
172    void compact();
173
174    //! Returns a full, dense matrix in \c m
175    void full(Mat<T> &m) const;
176
177    //! Returns a full, dense matrix
178    Mat<T> full() const;
179
180    //! Returns element of row \c r and column \c c
181    T operator()(int r, int c) const;
182
183    //! Set element (\c r, \c c ) equal to \c v
184    void set(int r, int c, T v);
185
186    //! Set a new element with index (\c r, \c c ) equal to \c v
187    void set_new(int r, int c, T v);
188
189    //! Add the element in row \c r and column \c c with \c v
190    void add_elem(const int r, const int c, const T v);
191
192    //! Set the sparse matrix to the all zero matrix (removes all non-zero elements)
193    void zeros();
194
195    //! Set the element in row \c r and column \c c to zero (i.e. clear that element if it contains a non-zero value)
196    void zero_elem(const int r, const int c);
197
198    //! Clear all non-zero elements of the sparse matrix
199    void clear();
200
201    //! Clear the element in row \c r and column \c c (if it contains a non-zero value)
202    void clear_elem(const int r, const int c);
203
204    //! Set submatrix defined by rows r1,r2 and columns c1,c2 to matrix m
205    void set_submatrix(int r1, int r2, int c1, int c2, const Mat<T> &m);
206
207    //! Set submatrix defined by upper-left element (\c r,\c c) and the size of matrix \c m to \c m
208    void set_submatrix(int r, int c, const Mat<T>& m);
209
210    //! Returns the sub-matrix from rows \c r1 to \c r2 and columns \c c1 to \c c2
211    Sparse_Mat<T> get_submatrix(int r1, int r2, int c1, int c2) const;
212
213    //! Returns the sub-matrix from columns \c c1 to \c c2 (all rows)
214    Sparse_Mat<T> get_submatrix_cols(int c1, int c2) const;
215
216    //! Returns column \c c of the Sparse_Mat in the Sparse_Vec \c v
217    void get_col(int c, Sparse_Vec<T> &v) const;
218
219    //! Returns column \c c of the Sparse_Mat
220    Sparse_Vec<T> get_col(int c) const;
221
222    //! Set column \c c of the Sparse_Mat
223    void set_col(int c, const Sparse_Vec<T> &v);
224
225    /*! Transpose the sparse matrix, return the result in \c m
226
227    Note: this function can be slow for large matrices.
228     */
229    void transpose(Sparse_Mat<T> &m) const;
230
231    /*! Returns the transpose of the sparse matrix
232
233    Note: this function can be slow for large matrices.
234    */
235    Sparse_Mat<T> transpose() const;
236
237    /*! Returns the transpose of the sparse matrix
238
239    Note: this function can be slow for large matrices.
240    */
241    // Sparse_Mat<T> T() const { return this->transpose(); };
242
243    //! Assign sparse matrix the value and dimensions of the sparse matrix \c m
244    void operator=(const Sparse_Mat<T> &m);
245
246    //! Assign sparse matrix the value and dimensions of the dense matrix \c m
247    void operator=(const Mat<T> &m);
248
249    //! Returns the sign inverse of all elements in the sparse matrix
250    Sparse_Mat<T> operator-() const;
251
252    //! Compare two sparse matricies. False if wrong sizes or different values
253    bool operator==(const Sparse_Mat<T> &m) const;
254
255    //! Add sparse matrix \c v to all non-zero elements of the sparse matrix
256    void operator+=(const Sparse_Mat<T> &v);
257
258    //! Add matrix \c v to all non-zero elements of the sparse matrix
259    void operator+=(const Mat<T> &v);
260
261    //! Subtract sparse matrix \c v from all non-zero elements of the sparse matrix
262    void operator-=(const Sparse_Mat<T> &v);
263
264    //! Subtract matrix \c v from all non-zero elements of the sparse matrix
265    void operator-=(const Mat<T> &v);
266
267    //! Multiply all non-zero elements of the sparse matrix with the scalar \c v
268    void operator*=(const T &v);
269
270    //! Divide all non-zero elements of the sparse matrix with the scalar \c v
271    void operator/=(const T &v);
272
273    //! Addition m1+m2 where m1 and m2 are sparse matrices
274    friend Sparse_Mat<T> operator+<>(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
275
276    //! Multiplication c*m where c is a scalar and m is a sparse matrix
277    friend Sparse_Mat<T> operator*<>(const T &c, const Sparse_Mat<T> &m);
278
279    //! Multiplication m1*m2 where m1 and m2 are sparse matrices
280    friend Sparse_Mat<T> operator*<>(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
281
282    //! Multiplication m*v where m is a sparse matrix and v is a sparse vector
283    friend Sparse_Vec<T> operator*<>(const Sparse_Mat<T> &m, const Sparse_Vec<T> &v);
284
285    //! Multiplication m*v where m is a sparse matrix and v is a full column vector
286    friend Vec<T> operator*<>(const Sparse_Mat<T> &m, const Vec<T> &v);
287
288    //! Multiplication v'*m where m is a sparse matrix and v is a full column vector
289    friend Vec<T> operator*<>(const Vec<T> &v, const Sparse_Mat<T> &m);
290
291    //! Multiplication m'*m where m is a sparse matrix. Returns a full, dense matrix
292    friend Mat<T> trans_mult <>(const Sparse_Mat<T> &m);
293
294    //! Multiplication m'*m where m is a sparse matrix, Returns a sparse matrix
295    friend Sparse_Mat<T> trans_mult_s <>(const Sparse_Mat<T> &m);
296
297    //! Multiplication m1'*m2 where m1 and m2 are sparse matrices
298    friend Sparse_Mat<T> trans_mult <>(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
299
300    //! Multiplication m'*v where m is a sparse matrix and v is a full column vector
301    friend Vec<T> trans_mult <>(const Sparse_Mat<T> &m, const Vec<T> &v);
302
303    //! Multiplication m1*m2' where m1 and m2 are sparse matrices
304    friend Sparse_Mat<T> mult_trans <>(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
305
306    private:
307    void init();
308    void alloc_empty();
309    void alloc(int row_data_size=200);
310    void free();
311
312    int n_rows, n_cols;
313    Sparse_Vec<T> *col;
314  };
315
316  /*!
317    \relates Sparse_Mat
318    \brief Sparse integer matrix
319  */
320  typedef Sparse_Mat<int> sparse_imat;
321
322  /*!
323    \relates Sparse_Mat
324    \brief Sparse double matrix
325  */
326  typedef Sparse_Mat<double> sparse_mat;
327
328  /*!
329    \relates Sparse_Mat
330    \brief Sparse complex<double> matrix
331  */
332  typedef Sparse_Mat<std::complex<double> > sparse_cmat;
333
334  //---------------------- Implementation starts here --------------------------------
335
336  template <class T>
337    void Sparse_Mat<T>::init()
338    {
339      n_rows = 0;
340      n_cols = 0;
341      col = 0;
342    }
343
344  template <class T>
345    void Sparse_Mat<T>::alloc_empty()
346    {
347      if (n_cols == 0)
348        col = 0;
349      else
350        col = new Sparse_Vec<T>[n_cols];
351    }
352
353  template <class T>
354    void Sparse_Mat<T>::alloc(int row_data_init)
355    {
356      if (n_cols == 0)
357        col = 0;
358      else
359        col = new Sparse_Vec<T>[n_cols];
360      for (int c=0; c<n_cols; c++)
361        col[c].set_size(n_rows, row_data_init);
362    }
363
364  template <class T>
365    void Sparse_Mat<T>::free()
366    {
367      delete [] col;
368      col = 0;
369    }
370
371  template <class T>
372    Sparse_Mat<T>::Sparse_Mat()
373    {
374      init();
375    }
376
377  template <class T>
378    Sparse_Mat<T>::Sparse_Mat(int rows, int cols, int row_data_init)
379    {
380      init();
381      n_rows = rows;
382      n_cols = cols;
383      alloc(row_data_init);
384    }
385
386  template <class T>
387    Sparse_Mat<T>::Sparse_Mat(const Sparse_Mat<T> &m)
388    {
389      init();
390      n_rows = m.n_rows;
391      n_cols = m.n_cols;
392      alloc_empty();
393
394      for (int c=0; c<n_cols; c++)
395        col[c] = m.col[c];
396    }
397
398  template <class T>
399    Sparse_Mat<T>::Sparse_Mat(const Mat<T> &m)
400    {
401      init();
402      n_rows = m.rows();
403      n_cols = m.cols();
404      alloc();
405
406      for (int c=0; c<n_cols; c++) {
407        for (int r=0; r<n_rows; r++) {
408          //if (abs(m(r,c)) != T(0))
409          if (m(r,c) != T(0))
410            col[c].set_new(r, m(r,c));
411        }
412        col[c].compact();
413      }
414    }
415
416  template <class T>
417    Sparse_Mat<T>::Sparse_Mat(const Mat<T> &m, T epsilon)
418    {
419      init();
420      n_rows = m.rows();
421      n_cols = m.cols();
422      alloc();
423
424      for (int c=0; c<n_cols; c++) {
425        for (int r=0; r<n_rows; r++) {
426                if (std::abs(m(r,c)) > std::abs(epsilon))
427            col[c].set_new(r, m(r,c));
428        }
429        col[c].compact();
430      }
431    }
432
433  template <class T>
434    Sparse_Mat<T>::~Sparse_Mat()
435    {
436      free();
437    }
438
439  template <class T>
440    void Sparse_Mat<T>::set_size(int rows, int cols, int row_data_init)
441    {
442      n_rows = rows;
443
444      //Allocate new memory for data if the number of columns has changed or if row_data_init != -1
445      if (cols!=n_cols||row_data_init!=-1) {
446        n_cols = cols;
447        free();
448        alloc(row_data_init);
449      }
450    }
451
452  template <class T>
453    int Sparse_Mat<T>::nnz()
454    {
455      int n=0;
456      for (int c=0; c<n_cols; c++)
457        n += col[c].nnz();
458
459      return n;
460    }
461
462  template <class T>
463    double Sparse_Mat<T>::density()
464    {
465      //return static_cast<double>(nnz())/(n_rows*n_cols);
466      return double(nnz())/(n_rows*n_cols);
467    }
468
469  template <class T>
470    void Sparse_Mat<T>::compact()
471    {
472      for (int c=0; c<n_cols; c++)
473        col[c].compact();
474    }
475
476  template <class T>
477    void Sparse_Mat<T>::full(Mat<T> &m) const
478    {
479      m.set_size(n_rows, n_cols);
480      m = T(0);
481      for (int c=0; c<n_cols; c++) {
482        for (int p=0; p<col[c].nnz(); p++)
483          m(col[c].get_nz_index(p),c) = col[c].get_nz_data(p);
484      }
485    }
486
487  template <class T>
488    Mat<T> Sparse_Mat<T>::full() const
489    {
490      Mat<T> r(n_rows, n_cols);
491      full(r);
492      return r;
493    }
494
495  template <class T>
496    T Sparse_Mat<T>::operator()(int r, int c) const
497    {
498      it_assert_debug(r>=0&&r<n_rows&&c>=0&&c<n_cols, "Incorrect input indexes given");
499      return col[c](r);
500    }
501
502  template <class T>
503    void Sparse_Mat<T>::set(int r, int c, T v)
504    {
505      it_assert_debug(r>=0&&r<n_rows&&c>=0&&c<n_cols, "Incorrect input indexes given");
506      col[c].set(r, v);
507    }
508
509  template <class T>
510    void Sparse_Mat<T>::set_new(int r, int c, T v)
511    {
512      it_assert_debug(r>=0&&r<n_rows&&c>=0&&c<n_cols, "Incorrect input indexes given");
513      col[c].set_new(r, v);
514    }
515
516  template <class T>
517    void Sparse_Mat<T>::add_elem(int r, int c, T v)
518    {
519      it_assert_debug(r>=0&&r<n_rows&&c>=0&&c<n_cols, "Incorrect input indexes given");
520      col[c].add_elem(r, v);
521    }
522
523  template <class T>
524    void Sparse_Mat<T>::zeros()
525    {
526      for (int c=0; c<n_cols; c++)
527        col[c].zeros();
528    }
529
530  template <class T>
531    void Sparse_Mat<T>::zero_elem(const int r, const int c)
532    {
533      it_assert_debug(r>=0&&r<n_rows&&c>=0&&c<n_cols, "Incorrect input indexes given");
534      col[c].zero_elem(r);
535    }
536
537  template <class T>
538    void Sparse_Mat<T>::clear()
539    {
540      for (int c=0; c<n_cols; c++)
541        col[c].clear();
542    }
543
544  template <class T>
545    void Sparse_Mat<T>::clear_elem(const int r, const int c)
546    {
547      it_assert_debug(r>=0&&r<n_rows&&c>=0&&c<n_cols, "Incorrect input indexes given");
548      col[c].clear_elem(r);
549    }
550
551  template <class T>
552    void Sparse_Mat<T>::set_submatrix(int r1, int r2, int c1, int c2, const Mat<T>& m)
553  {
554    if (r1 == -1) r1 = n_rows-1;
555    if (r2 == -1) r2 = n_rows-1;
556    if (c1 == -1) c1 = n_cols-1;
557    if (c2 == -1) c2 = n_cols-1;
558
559    it_assert_debug(r1>=0 && r2>=0 && r1<n_rows && r2<n_rows &&
560               c1>=0 && c2>=0 && c1<n_cols && c2<n_cols, "Sparse_Mat<Num_T>::set_submatrix(): index out of range");
561
562    it_assert_debug(r2>=r1 && c2>=c1, "Sparse_Mat<Num_T>::set_submatrix: r2<r1 or c2<c1");
563    it_assert_debug(m.rows() == r2-r1+1 && m.cols() == c2-c1+1, "Mat<Num_T>::set_submatrix(): sizes don't match");
564
565    for (int i=0 ; i<m.rows() ; i++) {
566      for (int j=0 ; j<m.cols() ; j++) {
567        set(r1+i, c1+j, m(i,j));
568      }
569    }
570  }
571
572  template <class T>
573    void Sparse_Mat<T>::set_submatrix(int r, int c, const Mat<T>& m)
574  {
575    it_assert_debug(r>=0 && r+m.rows()<=n_rows &&
576               c>=0 && c+m.cols()<=n_cols, "Sparse_Mat<Num_T>::set_submatrix(): index out of range");
577
578    for (int i=0 ; i<m.rows() ; i++) {
579      for (int j=0 ; j<m.cols() ; j++) {
580        set(r+i, c+j, m(i,j));
581      }
582    }
583  }
584
585  template <class T>
586    Sparse_Mat<T> Sparse_Mat<T>::get_submatrix(int r1, int r2, int c1, int c2) const
587    {
588      it_assert_debug(r1<=r2 && r1>=0 && r1<n_rows && c1<=c2 && c1>=0 && c1<n_cols,
589                "Sparse_Mat<T>::get_submatrix(): illegal input variables");
590
591      Sparse_Mat<T> r(r2-r1+1, c2-c1+1);
592
593      for (int c=c1; c<=c2; c++)
594        r.col[c-c1] = col[c].get_subvector(r1, r2);
595      r.compact();
596
597      return r;
598    }
599
600  template <class T>
601    Sparse_Mat<T> Sparse_Mat<T>::get_submatrix_cols(int c1, int c2) const
602    {
603      it_assert_debug(c1<=c2 && c1>=0 && c1<n_cols, "Sparse_Mat<T>::get_submatrix_cols()");
604      Sparse_Mat<T> r(n_rows, c2-c1+1, 0);
605
606      for (int c=c1; c<=c2; c++)
607        r.col[c-c1] = col[c];
608      r.compact();
609
610      return r;
611    }
612
613  template <class T>
614    void Sparse_Mat<T>::get_col(int c, Sparse_Vec<T> &v) const
615    {
616      it_assert(c>=0 && c<n_cols, "Sparse_Mat<T>::get_col()");
617      v = col[c];
618    }
619
620  template <class T>
621    Sparse_Vec<T> Sparse_Mat<T>::get_col(int c) const
622    {
623      it_assert(c>=0 && c<n_cols, "Sparse_Mat<T>::get_col()");
624      return col[c];
625    }
626
627  template <class T>
628    void Sparse_Mat<T>::set_col(int c, const Sparse_Vec<T> &v)
629    {
630      it_assert(c>=0 && c<n_cols, "Sparse_Mat<T>::set_col()");
631      col[c] = v;
632    }
633
634  template <class T>
635    void Sparse_Mat<T>::transpose(Sparse_Mat<T> &m) const
636  {
637    m.set_size(n_cols, n_rows);
638    for (int c=0; c<n_cols; c++) {
639      for (int p=0; p<col[c].nnz(); p++)
640        m.col[col[c].get_nz_index(p)].set_new(c, col[c].get_nz_data(p));
641    }
642  }
643
644  template <class T>
645    Sparse_Mat<T> Sparse_Mat<T>::transpose() const
646  {
647    Sparse_Mat<T> m;
648    transpose(m);
649    return m;
650  }
651
652  template <class T>
653    void Sparse_Mat<T>::operator=(const Sparse_Mat<T> &m)
654    {
655      free();
656      n_rows = m.n_rows;
657      n_cols = m.n_cols;
658      alloc_empty();
659
660      for (int c=0; c<n_cols; c++)
661        col[c] = m.col[c];
662    }
663
664  template <class T>
665    void Sparse_Mat<T>::operator=(const Mat<T> &m)
666    {
667      free();
668      n_rows = m.rows();
669      n_cols = m.cols();
670      alloc();
671
672      for (int c=0; c<n_cols; c++) {
673        for (int r=0; r<n_rows; r++) {
674          if (m(r,c) != T(0))
675            col[c].set_new(r, m(r,c));
676        }
677        col[c].compact();
678      }
679    }
680
681  template <class T>
682    Sparse_Mat<T> Sparse_Mat<T>::operator-() const
683    {
684      Sparse_Mat r(n_rows, n_cols, 0);
685
686      for (int c=0; c<n_cols; c++) {
687        r.col[c].resize_data(col[c].nnz());
688        for (int p=0; p<col[c].nnz(); p++)
689          r.col[c].set_new(col[c].get_nz_index(p), -col[c].get_nz_data(p));
690      }
691
692      return r;
693    }
694
695  template <class T>
696    bool Sparse_Mat<T>::operator==(const Sparse_Mat<T> &m) const
697    {
698      if (n_rows!=m.n_rows || n_cols!=m.n_cols)
699        return false;
700      for (int c=0; c<n_cols; c++) {
701        if (!(col[c] == m.col[c]))
702          return false;
703      }
704      // If they passed all tests, they must be equal
705      return true;
706    }
707
708  template <class T>
709    void Sparse_Mat<T>::operator+=(const Sparse_Mat<T> &m)
710    {
711      it_assert_debug(m.rows()==n_rows&&m.cols()==n_cols, "Addition of unequal sized matrices is not allowed");
712
713      Sparse_Vec<T> v;
714      for (int c=0; c<n_cols; c++) {
715        m.get_col(c,v);
716        col[c]+=v;
717      }
718    }
719
720  template <class T>
721    void Sparse_Mat<T>::operator+=(const Mat<T> &m)
722    {
723      it_assert_debug(m.rows()==n_rows&&m.cols()==n_cols, "Addition of unequal sized matrices is not allowed");
724
725      for (int c=0; c<n_cols; c++)
726        col[c]+=(m.get_col(c));
727    }
728
729  template <class T>
730    void Sparse_Mat<T>::operator-=(const Sparse_Mat<T> &m)
731    {
732      it_assert_debug(m.rows()==n_rows&&m.cols()==n_cols, "Subtraction of unequal sized matrices is not allowed");
733
734      Sparse_Vec<T> v;
735      for (int c=0; c<n_cols; c++) {
736        m.get_col(c,v);
737        col[c]-=v;
738      }
739    }
740
741  template <class T>
742    void Sparse_Mat<T>::operator-=(const Mat<T> &m)
743    {
744      it_assert_debug(m.rows()==n_rows&&m.cols()==n_cols, "Subtraction of unequal sized matrices is not allowed");
745
746      for (int c=0; c<n_cols; c++)
747        col[c]-=(m.get_col(c));
748    }
749
750  template <class T>
751    void Sparse_Mat<T>::operator*=(const T &m)
752    {
753      for (int c=0; c<n_cols; c++)
754        col[c]*=m;
755    }
756
757  template <class T>
758    void Sparse_Mat<T>::operator/=(const T &m)
759    {
760      for (int c=0; c<n_cols; c++)
761        col[c]/=m;
762    }
763
764  template <class T>
765    Sparse_Mat<T> operator+(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2)
766    {
767      it_assert_debug(m1.n_cols == m2.n_cols && m1.n_rows == m2.n_rows , "Sparse_Mat<T> + Sparse_Mat<T>");
768
769      Sparse_Mat<T> m(m1.n_rows, m1.n_cols, 0);
770
771      for (int c=0; c<m.n_cols; c++)
772        m.col[c] = m1.col[c] + m2.col[c];
773
774      return m;
775    }
776
777  // This function added by EGL, May'05
778  template <class T>
779    Sparse_Mat<T> operator*(const T &c, const Sparse_Mat<T> &m)
780    {
781      int i,j;
782      Sparse_Mat<T> ret(m.n_rows,m.n_cols);
783      for (j=0; j<m.n_cols; j++) {
784        for (i=0; i<m.col[j].nnz(); i++) {
785          T x = c*m.col[j].get_nz_data(i);
786          int k = m.col[j].get_nz_index(i);
787          ret.set_new(k,j,x);
788        }
789      }
790      return ret;
791    }
792
793  template <class T>
794    Sparse_Mat<T> operator*(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2)
795    {
796      it_assert_debug(m1.n_cols == m2.n_rows, "Sparse_Mat<T> * Sparse_Mat<T>");
797
798      Sparse_Mat<T> ret(m1.n_rows, m2.n_cols);
799
800      for (int c=0; c<m2.n_cols; c++) {
801        Sparse_Vec<T> &m2colc=m2.col[c];
802        for (int p2=0; p2<m2colc.nnz(); p2++) {
803          Sparse_Vec<T> &mcol = m1.col[m2colc.get_nz_index(p2)];
804          T x = m2colc.get_nz_data(p2);
805          for (int p1=0; p1<mcol.nnz(); p1++) {
806            int r = mcol.get_nz_index(p1);
807            T inc = mcol.get_nz_data(p1) *x;
808            ret.col[c].add_elem(r,inc);
809          }
810        }
811      }
812      // old code
813/*       for (int c=0; c<m2.n_cols; c++) { */
814/*      for (int p2=0; p2<m2.col[c].nnz(); p2++) { */
815/*        Sparse_Vec<T> &mcol = m1.col[m2.col[c].get_nz_index(p2)]; */
816/*        for (int p1=0; p1<mcol.nnz(); p1++) { */
817/*          int r = mcol.get_nz_index(p1); */
818/*          T inc = mcol.get_nz_data(p1) * m2.col[c].get_nz_data(p2); */
819/*          ret.col[c].add_elem(r,inc); */
820/*        } */
821/*      } */
822/*       } */
823      ret.compact();
824      return ret;
825    }
826
827
828  // This is apparently buggy.
829/*   template <class T> */
830/*     Sparse_Mat<T> operator*(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2) */
831/*     { */
832/*       it_assert_debug(m1.n_cols == m2.n_rows, "Sparse_Mat<T> * Sparse_Mat<T>"); */
833
834/*       Sparse_Mat<T> ret(m1.n_rows, m2.n_cols); */
835/*       ivec occupied_by(ret.n_rows), pos(ret.n_rows); */
836/*       for (int rp=0; rp<m1.n_rows; rp++) */
837/*      occupied_by[rp] = -1; */
838/*       for (int c=0; c<ret.n_cols; c++) { */
839/*      Sparse_Vec<T> &m2col = m2.col[c]; */
840/*      for (int p2=0; p2<m2col.nnz(); p2++) { */
841/*        Sparse_Vec<T> &m1col = m1.col[m2col.get_nz_index(p2)]; */
842/*        for (int p1=0; p1<m1col.nnz(); p1++) { */
843/*          int r = m1col.get_nz_index(p1); */
844/*          T inc = m1col.get_nz_data(p1) * m2col.get_nz_data(p2); */
845/*          if (occupied_by[r] == c) { */
846/*            int index=ret.col[c].get_nz_index(pos[r]); */
847/*            ret.col[c].add_elem(index,inc); */
848/*          } */
849/*          else { */
850/*            occupied_by[r] = c; */
851/*            pos[r] = ret.col[c].nnz(); */
852/*            ret.col[c].set_new(r, inc); */
853/*          } */
854/*        } */
855/*      } */
856/*       } */
857/*       ret.compact(); */
858
859/*       return ret; */
860/*     } */
861
862
863  // This function added by EGL, May'05
864  template <class T>
865    Sparse_Vec<T> operator*(const Sparse_Mat<T> &m, const Sparse_Vec<T> &v)
866    {
867      it_assert_debug(m.n_cols == v.size(), "Sparse_Mat<T> * Sparse_Vec<T>");
868
869      Sparse_Vec<T> ret(m.n_rows);
870
871      /* The two lines below added because the input parameter "v" is
872         declared const, but the some functions (e.g., nnz()) change
873         the vector... Is there a better workaround? */
874      Sparse_Vec<T> vv = v;
875
876      for (int p2=0; p2<vv.nnz(); p2++) {
877        Sparse_Vec<T> &mcol = m.col[vv.get_nz_index(p2)];
878        T x = vv.get_nz_data(p2);
879        for (int p1=0; p1<mcol.nnz(); p1++) {
880          int r = mcol.get_nz_index(p1);
881          T inc = mcol.get_nz_data(p1) * x;
882          ret.add_elem(r,inc);
883        }
884      }
885      ret.compact();
886      return ret;
887    }
888
889
890  template <class T>
891    Vec<T> operator*(const Sparse_Mat<T> &m, const Vec<T> &v)
892    {
893      it_assert_debug(m.n_cols == v.size(), "Sparse_Mat<T> * Vec<T>");
894
895      Vec<T> r(m.n_rows);
896      r.clear();
897
898      for (int c=0; c<m.n_cols; c++) {
899        for (int p=0; p<m.col[c].nnz(); p++)
900          r(m.col[c].get_nz_index(p)) += m.col[c].get_nz_data(p) * v(c);
901      }
902
903      return r;
904    }
905
906  template <class T>
907    Vec<T> operator*(const Vec<T> &v, const Sparse_Mat<T> &m)
908    {
909      it_assert_debug(v.size() == m.n_rows, "Vec<T> * Sparse_Mat<T>");
910
911      Vec<T> r(m.n_cols);
912      r.clear();
913
914      for (int c=0; c<m.n_cols; c++)
915        r[c] = v * m.col[c];
916
917      return r;
918    }
919
920  template <class T>
921    Mat<T> trans_mult(const Sparse_Mat<T> &m)
922    {
923      Mat<T> ret(m.n_cols, m.n_cols);
924      Vec<T> col;
925      for (int c=0; c<ret.cols(); c++) {
926        m.col[c].full(col);
927        for (int r=0; r<c; r++) {
928          T tmp = m.col[r] * col;
929          ret(r,c) = tmp;
930          ret(c,r) = tmp;
931        }
932        ret(c,c) = m.col[c].sqr();
933      }
934
935      return ret;
936    }
937
938  template <class T>
939    Sparse_Mat<T> trans_mult_s(const Sparse_Mat<T> &m)
940    {
941      Sparse_Mat<T> ret(m.n_cols, m.n_cols);
942      Vec<T> col;
943      T tmp;
944      for (int c=0; c<ret.n_cols; c++) {
945        m.col[c].full(col);
946        for (int r=0; r<c; r++) {
947          tmp = m.col[r] * col;
948          if (tmp != T(0)) {
949            ret.col[c].set_new(r, tmp);
950            ret.col[r].set_new(c, tmp);
951          }
952        }
953        tmp = m.col[c].sqr();
954        if (tmp != T(0))
955          ret.col[c].set_new(c, tmp);
956      }
957
958      return ret;
959    }
960
961  template <class T>
962    Sparse_Mat<T> trans_mult(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2)
963    {
964      it_assert_debug(m1.n_rows == m2.n_rows, "trans_mult()");
965
966      Sparse_Mat<T> ret(m1.n_cols, m2.n_cols);
967      Vec<T> col;
968      for (int c=0; c<ret.n_cols; c++) {
969        m2.col[c].full(col);
970        for (int r=0; r<ret.n_rows; r++)
971          ret.col[c].set_new(r, m1.col[r] * col);
972      }
973
974      return ret;
975    }
976
977  template <class T>
978    Vec<T> trans_mult(const Sparse_Mat<T> &m, const Vec<T> &v)
979    {
980      Vec<T> r(m.n_cols);
981      for (int c=0; c<m.n_cols; c++)
982        r(c) = m.col[c] * v;
983
984      return r;
985    }
986
987  template <class T>
988    Sparse_Mat<T> mult_trans(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2)
989    {
990      return trans_mult(m1.transpose(),m2.transpose());
991    }
992
993  //! Convert a dense matrix \c m into its sparse representation
994  template <class T>
995    inline Sparse_Mat<T> sparse(const Mat<T> &m, T epsilon)
996    {
997      Sparse_Mat<T> s(m, epsilon);
998      return s;
999    }
1000
1001  //! Convert a sparse matrix \c s into its dense representation
1002  template <class T>
1003    inline Mat<T> full(const Sparse_Mat<T> &s)
1004    {
1005      Mat<T> m;
1006      s.full(m);
1007      return m;
1008    }
1009
1010  //! Transpose a sparse matrix \c s
1011  template <class T>
1012    inline Sparse_Mat<T> transpose(const Sparse_Mat<T> &s)
1013    {
1014      Sparse_Mat<T> m;
1015      s.transpose(m);
1016      return m;
1017    }
1018
1019  //! \cond
1020
1021  // ---------------------------------------------------------------------
1022  // Instantiations
1023  // ---------------------------------------------------------------------
1024
1025#ifdef HAVE_EXTERN_TEMPLATE
1026
1027  extern template class Sparse_Mat<int>;
1028  extern template class Sparse_Mat<double>;
1029  extern template class Sparse_Mat<std::complex<double> >;
1030
1031  extern template sparse_imat operator+(const sparse_imat &, const sparse_imat &);
1032  extern template sparse_mat operator+(const sparse_mat &, const sparse_mat &);
1033  extern template sparse_cmat operator+(const sparse_cmat &, const sparse_cmat &);
1034
1035  extern template sparse_imat operator*(const sparse_imat &, const sparse_imat &);
1036  extern template sparse_mat operator*(const sparse_mat &, const sparse_mat &);
1037  extern template sparse_cmat operator*(const sparse_cmat &, const sparse_cmat &);
1038
1039  extern template ivec operator*(const ivec &, const sparse_imat &);
1040  extern template vec operator*(const vec &, const sparse_mat &);
1041  extern template cvec operator*(const cvec &, const sparse_cmat &);
1042
1043  extern template ivec operator*(const sparse_imat &, const ivec &);
1044  extern template vec operator*(const sparse_mat &, const vec &);
1045  extern template cvec operator*(const sparse_cmat &, const cvec &);
1046
1047  extern template imat trans_mult(const sparse_imat &);
1048  extern template mat trans_mult(const sparse_mat &);
1049  extern template cmat trans_mult(const sparse_cmat &);
1050
1051  extern template sparse_imat trans_mult_s(const sparse_imat &);
1052  extern template sparse_mat trans_mult_s(const sparse_mat &);
1053  extern template sparse_cmat trans_mult_s(const sparse_cmat &);
1054
1055  extern template sparse_imat trans_mult(const sparse_imat &, const sparse_imat &);
1056  extern template sparse_mat trans_mult(const sparse_mat &, const sparse_mat &);
1057  extern template sparse_cmat trans_mult(const sparse_cmat &, const sparse_cmat &);
1058
1059  extern template ivec trans_mult(const sparse_imat &, const ivec &);
1060  extern template vec trans_mult(const sparse_mat &, const vec &);
1061  extern template cvec trans_mult(const sparse_cmat &, const cvec &);
1062
1063  extern template sparse_imat mult_trans(const sparse_imat &, const sparse_imat &);
1064  extern template sparse_mat mult_trans(const sparse_mat &, const sparse_mat &);
1065  extern template sparse_cmat mult_trans(const sparse_cmat &, const sparse_cmat &);
1066
1067#endif // HAVE_EXTERN_TEMPLATE
1068
1069  //! \endcond
1070
1071} // namespace itpp
1072
1073#endif // #ifndef SMAT_H
Note: See TracBrowser for help on using the browser.