root/win32/itpp-4.0.1/itpp/base/mat.h @ 129

Revision 35, 67.8 kB (checked in by mido, 16 years ago)

zasadni zmeny ve /win32

Line 
1/*!
2 * \file
3 * \brief Matrix Class Definitions
4 * \author Tony Ottosson, Tobias Ringstrom, Adam Piatyszek and Conrad Sanderson
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 MAT_H
31#define MAT_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/itassert.h>
40#include <itpp/base/math/misc.h>
41#include <itpp/base/factory.h>
42
43
44namespace itpp {
45
46  // Declaration of Vec
47  template<class Num_T> class Vec;
48  // Declaration of Mat
49  template<class Num_T> class Mat;
50  // Declaration of bin
51  class bin;
52
53  //! Horizontal concatenation of two matrices
54  template<class Num_T> const Mat<Num_T> concat_horizontal(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
55  //! Vertical concatenation of two matrices
56  template<class Num_T> const Mat<Num_T> concat_vertical(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
57
58  //! Addition of two matricies
59  template<class Num_T> const Mat<Num_T> operator+(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
60  //! Addition of a matrix and a scalar
61  template<class Num_T> const Mat<Num_T> operator+(const Mat<Num_T> &m, Num_T t);
62  //! Addition of a scalar and a matrix
63  template<class Num_T> const Mat<Num_T> operator+(Num_T t, const Mat<Num_T> &m);
64
65  //! Subtraction of two matrices
66  template<class Num_T> const Mat<Num_T> operator-(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
67  //! Subtraction of matrix and scalar
68  template<class Num_T> const Mat<Num_T> operator-(const Mat<Num_T> &m, Num_T t);
69  //! Subtraction of scalar and matrix
70  template<class Num_T> const Mat<Num_T> operator-(Num_T t, const Mat<Num_T> &m);
71  //! Negation of matrix
72  template<class Num_T> const Mat<Num_T> operator-(const Mat<Num_T> &m);
73
74  //! Multiplication of two matricies
75  template<class Num_T> const Mat<Num_T> operator*(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
76  //! Multiplication of matrix and vector
77  template<class Num_T> const Vec<Num_T> operator*(const Mat<Num_T> &m, const Vec<Num_T> &v);
78  //! Multiplication of vector and matrix (only works for a matrix that is a row vector)
79  template<class Num_T> const Mat<Num_T> operator*(const Vec<Num_T> &v, const Mat<Num_T> &m);
80  //! Multiplication of matrix and scalar
81  template<class Num_T> const Mat<Num_T> operator*(const Mat<Num_T> &m, Num_T t);
82  //! Multiplication of scalar and matrix
83  template<class Num_T> const Mat<Num_T> operator*(Num_T t, const Mat<Num_T> &m);
84
85  //! Element wise multiplication of two matrices. Same functionality as Matlab/Octave expression A .* B
86  template<class Num_T> const Mat<Num_T> elem_mult(const Mat<Num_T> &A, const Mat<Num_T> &B);
87  //! Element wise multiplication of two matrices, storing the result in matrix \c out (which is re-sized if necessary)
88  template<class Num_T> void elem_mult_out(const Mat<Num_T> &A, const Mat<Num_T> &B, Mat<Num_T> &out);
89  //! Element wise multiplication of three matrices, storing the result in matrix \c out (which is re-sized if necessary)
90  template<class Num_T> void elem_mult_out(const Mat<Num_T> &A, const Mat<Num_T> &B, const Mat<Num_T> &C, Mat<Num_T> &out);
91  //! Element wise multiplication of four matrices, storing the result in matrix \c out (which is re-sized if necessary)
92  template<class Num_T> void elem_mult_out(const Mat<Num_T> &A, const Mat<Num_T> &B, const Mat<Num_T> &C, const Mat<Num_T> &D, Mat<Num_T> &out);
93  //! In-place element wise multiplication of two matrices. Fast version of B = elem_mult(A,B)
94  template<class Num_T> void elem_mult_inplace(const Mat<Num_T> &A, Mat<Num_T> &B);
95  //! Element wise multiplication of two matrices, followed by summation of the resultant elements. Fast version of sumsum(elem_mult(A,B))
96  template<class Num_T> Num_T elem_mult_sum(const Mat<Num_T> &A, const Mat<Num_T> &B);
97
98  //! Division of matrix and scalar
99  template<class Num_T> const Mat<Num_T> operator/(const Mat<Num_T> &m, Num_T t);
100
101  //! Element wise division of two matrices. Same functionality as Matlab/Octave expression A ./ B
102  template<class Num_T> const Mat<Num_T> elem_div(const Mat<Num_T> &A, const Mat<Num_T> &B);
103  //! Element wise division of two matrices, storing the result in matrix \c out (which is re-sized if necessary)
104  template<class Num_T> void elem_div_out(const Mat<Num_T> &A, const Mat<Num_T> &B, Mat<Num_T> &out);
105  //! Element wise division of two matrices, followed by summation of the resultant elements. Fast version of sumsum(elem_div(A,B))
106  template<class Num_T> Num_T elem_div_sum(const Mat<Num_T> &A, const Mat<Num_T> &B);
107
108  // -------------------------------------------------------------------------------------
109  // Declaration of Mat
110  // -------------------------------------------------------------------------------------
111
112  /*!
113    \ingroup arr_vec_mat
114    \brief Matrix Class (Templated)
115    \author Tony Ottosson, Tobias Ringstrom, Adam Piatyszek and Conrad Sanderson
116
117    Matrices can be of arbitrarily types, but conversions and functions are
118    prepared for \c bin, \c short, \c int, \c double, and \c complex<double>
119    vectors and these are predefined as: \c bmat, \c smat, \c imat, \c mat,
120    and \c cmat. \c double and \c complex<double> are usually \c double and
121    \c complex<double> respectively. However, this can be changed when
122    compiling the it++ (see installation notes for more details). (Note: for
123    binary matrices, an alternative to the bmat class is \c GF2mat and
124    \c GF2mat_dense, which offer a more memory efficient representation and
125    additional functions for linear algebra.)
126
127    Examples:
128
129    Matrix Constructors:
130    When constructing a matrix without dimensions (memory) use
131    \code mat temp; \endcode
132    For construction of a matrix of a given size use
133    \code mat temp(rows, cols); \endcode
134    It is also possible to assign the constructed matrix the value and dimension
135    of another matrix by
136    \code vec temp(inmatrix); \endcode
137    If you have explicit values you would like to assign to the matrix it is
138    possible to do this using strings as:
139    \code
140    mat a("0 0.7;5 9.3"); // that is a = [0, 0.7; 5, 9.3]
141    mat a="0 0.7;5 9.3";  // the constructor are called implicitly
142    \endcode
143    It is also possible to change dimension by
144    \code temp.set_size(new_rows, new_cols, false); \endcode
145    where \c false is used to indicate that the old values in \c temp
146    is not copied. If you like to preserve the values use \c true.
147
148    There are a number of methods to access parts of a matrix. Examples are
149    \code
150    a(5,3);     // Element number (5,3)
151    a(5,9,3,5);  // Sub-matrix from rows 5, 6, 7, 8, 9 the columns 3, 4, and 5
152    a.get_row(10);  // Row 10
153    a.get_col(10); // Column 10
154    \endcode
155
156    It is also possible to modify parts of a vector as e.g. in
157    \code
158    a.set_row(5, invector);    // Set row 5 to \c invector
159    a.set_col(3, invector); // Set column 3 to \c invector
160    a.copy_col(1, 5); // Copy column 5 to column 1
161    a.swap_cols(1, 5); // Swap the contents of columns 1 and 5
162    \endcode
163
164    It is of course also possible to perform the common linear algebra
165    methods such as addition, subtraction, and matrix multiplication. Observe
166    though, that vectors are assumed to be column-vectors in operations with
167    matrices.
168
169    Most elementary functions such as sin(), cosh(), log(), abs(), ..., are
170    available as operations on the individual elements of the matrices. Please
171    see the individual functions for more details.
172
173    By default, the Mat elements are created using the default constructor for
174    the element type. This can be changed by specifying a suitable Factory in
175    the Mat constructor call; see Detailed Description for Factory.
176  */
177  template<class Num_T>
178  class Mat {
179  public:
180    //! The type of the matrix values
181    typedef Num_T value_type;
182
183    //! Default constructor. An element factory \c f can be specified
184    explicit Mat(const Factory &f = DEFAULT_FACTORY);
185    //! Create a matrix of size (inrow, incol). An element factory \c f can be specified
186    Mat(int inrow, int incol, const Factory &f = DEFAULT_FACTORY);
187    //! Copy constructor
188    Mat(const Mat<Num_T> &m);
189    //! Constructor, similar to the copy constructor, but also takes an element factory \c f as argument
190    Mat(const Mat<Num_T> &m, const Factory &f);
191    //! Create a copy of the vector \c invector treated as a column vector. An element factory \c f can be specified
192    Mat(const Vec<Num_T> &invector, const Factory &f = DEFAULT_FACTORY);
193    //! Set matrix equal to values in string. An element factory \c f can be specified
194    Mat(const std::string &str, const Factory &f = DEFAULT_FACTORY);
195    //! Set matrix equal to values in string. An element factory \c f can be specified
196    Mat(const char *str, const Factory &f = DEFAULT_FACTORY);
197    /*!
198      \brief Constructor taking a C-array as input. Copies all data. An element factory \c f can be specified
199
200      By default the matrix is stored as a RowMajor matrix (i.e. listing elements in sequence
201      beginning with the first column).
202    */
203    Mat(const Num_T *c_array, int rows, int cols, bool RowMajor = true, const Factory &f = DEFAULT_FACTORY);
204
205    //! Destructor
206    ~Mat();
207
208    //! The number of columns
209    int cols() const { return no_cols; }
210    //! The number of rows
211    int rows() const { return no_rows; }
212    //! The number of elements
213    int size() const { return datasize; }
214    //! Set size of matrix. If copy = true then keep the data before resizing.
215    void set_size(int inrow, int incol, bool copy = false);
216    //! Set matrix equal to the all zero matrix
217    void zeros();
218    //! Set matrix equal to the all zero matrix
219    void clear() { zeros(); }
220    //! Set matrix equal to the all one matrix
221    void ones();
222    //! Set matrix equal to values in \c values
223    void set(const char *str);
224    //! Set matrix equal to values in the string \c str
225    void set(const std::string &str);
226
227    //! Get element (R,C) from matrix
228    const Num_T &operator()(int R, int C) const;
229    //! Get element (R,C) from matrix
230    Num_T &operator()(int R, int C);
231    //! Get element \c index using linear addressing (by rows)
232    const Num_T &operator()(int index) const;
233    //! Get element \c index using linear addressing (by rows)
234    Num_T &operator()(int index);
235    //! Get element (R,C) from matrix
236    const Num_T &get(int R,int C) const;
237    //! Set element (R,C) of matrix
238    void set(int R,int C, const Num_T &v);
239
240    /*!
241      \brief Sub-matrix from row \c r1 to row \c r2 and columns \c c1 to \c c2.
242
243      Value -1 indicates the last row and column, respectively.
244    */
245    const Mat<Num_T> operator()(int r1, int r2, int c1, int c2) const;
246    /*!
247      \brief Sub-matrix from row \c r1 to row \c r2 and columns \c c1 to \c c2.
248
249      Value -1 indicates the last row and column, respectively.
250    */
251    const Mat<Num_T> get(int r1, int r2, int c1, int c2) const;
252
253    //! Get row \c Index
254    const Vec<Num_T> get_row(int Index) const ;
255    //! Get rows \c r1 through \c r2
256    const Mat<Num_T> get_rows(int r1, int r2) const;
257    //! Get the rows specified by \c indexlist
258    const Mat<Num_T> get_rows(const Vec<int> &indexlist) const;
259    //! Get column \c Index
260    const Vec<Num_T> get_col(int Index) const ;
261    //! Get columns \c c1 through \c c2
262    const Mat<Num_T> get_cols(int c1, int c2) const;
263    //! Get the columns specified by \c indexlist
264    const Mat<Num_T> get_cols(const Vec<int> &indexlist) const;
265    //! Set row \c Index to \c invector
266    void set_row(int Index, const Vec<Num_T> &invector);
267    //! Set column \c Index to \c invector
268    void set_col(int Index, const Vec<Num_T> &invector);
269    //! Set rows to matrix \c m, staring from row \c r
270    void set_rows(int r, const Mat<Num_T> &m);
271    //! Set colums to matrix \c m, starting from column \c c
272    void set_cols(int c, const Mat<Num_T> &m);
273    //! Copy row \c from onto row \c to
274    void copy_row(int to, int from);
275    //! Copy column \c from onto column \c to
276    void copy_col(int to, int from);
277    //! Swap the rows \c r1 and \c r2
278    void swap_rows(int r1, int r2);
279    //! Swap the columns \c c1 and \c c2
280    void swap_cols(int c1, int c2);
281
282    //! Set submatrix defined by rows r1,r2 and columns c1,c2 to matrix m
283    void set_submatrix(int r1, int r2, int c1, int c2, const Mat<Num_T> &m);
284    //! Set submatrix defined by upper-left element (r,c) and the size of matrix m to m
285    void set_submatrix(int r, int c, const Mat<Num_T> &m);
286    //! Set all elements of submatrix defined by rows r1,r2 and columns c1,c2 to value t
287    void set_submatrix(int r1, int r2, int c1, int c2, const Num_T t);
288
289    //! Delete row number \c r
290    void del_row(int r);
291    //! Delete rows from \c r1 to \c r2
292    void del_rows(int r1, int r2);
293    //! Delete column number \c c
294    void del_col(int c);
295    //! Delete columns from \c c1 to \c c2
296    void del_cols(int c1, int c2);
297    //! Insert vector \c in at row number \c r, the matrix can be empty.
298    void ins_row(int r, const Vec<Num_T> &in);
299    //! Insert vector \c in at column number \c c, the matrix can be empty.
300    void ins_col(int c, const Vec<Num_T> &in);
301    //! Append vector \c to the bottom of the matrix, the matrix can be empty.
302    void append_row(const Vec<Num_T> &in);
303    //! Append vector \c to the right of the matrix, the matrix can be empty.
304    void append_col(const Vec<Num_T> &in);
305
306    //! Matrix transpose
307    const Mat<Num_T> transpose() const;
308    //! Matrix transpose
309    const Mat<Num_T> T() const { return this->transpose(); }
310    //! Hermitian matrix transpose (conjugate transpose)
311    const Mat<Num_T> hermitian_transpose() const;
312    //! Hermitian matrix transpose (conjugate transpose)
313    const Mat<Num_T> H() const { return this->hermitian_transpose(); }
314
315    //! Concatenate the matrices \c m1 and \c m2 horizontally
316    friend const Mat<Num_T> concat_horizontal <>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
317    //! Concatenate the matrices \c m1 and \c m2 vertically
318    friend const Mat<Num_T> concat_vertical <>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
319
320    //! Set all elements of the matrix equal to \c t
321    Mat<Num_T>& operator=(Num_T t);
322    //! Set matrix equal to \c m
323    Mat<Num_T>& operator=(const Mat<Num_T> &m);
324    //! Set matrix equal to the vector \c v, assuming column vector
325    Mat<Num_T>& operator=(const Vec<Num_T> &v);
326    //! Set matrix equal to values in the string
327    Mat<Num_T>& operator=(const char *values);
328
329    //! Addition of matrices
330    Mat<Num_T>& operator+=(const Mat<Num_T> &m);
331    //! Addition of scalar to matrix
332    Mat<Num_T>& operator+=(Num_T t);
333    //! Addition of two matrices
334    friend const  Mat<Num_T> operator+<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
335    //! Addition of matrix and scalar
336    friend const Mat<Num_T> operator+<>(const Mat<Num_T> &m, Num_T t);
337    //! Addition of scalar and matrix
338    friend const Mat<Num_T> operator+<>(Num_T t, const Mat<Num_T> &m);
339
340    //! Subtraction of matrix
341    Mat<Num_T>& operator-=(const Mat<Num_T> &m);
342    //! Subtraction of scalar from matrix
343    Mat<Num_T>& operator-=(Num_T t);
344    //! Subtraction of \c m2 from \c m1
345    friend const Mat<Num_T> operator-<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
346    //! Subraction of scalar from matrix
347    friend const Mat<Num_T> operator-<>(const Mat<Num_T> &m, Num_T t);
348    //! Subtract matrix from scalar
349    friend const Mat<Num_T> operator-<>(Num_T t, const Mat<Num_T> &m);
350    //! Subraction of matrix
351    friend const Mat<Num_T> operator-<>(const Mat<Num_T> &m);
352
353    //! Matrix multiplication
354    Mat<Num_T>& operator*=(const Mat<Num_T> &m);
355    //! Multiplication by a scalar
356    Mat<Num_T>& operator*=(Num_T t);
357    //! Multiplication of two matrices
358    friend const Mat<Num_T> operator*<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
359    //! Multiplication of matrix \c m and vector \c v (column vector)
360    friend const Vec<Num_T> operator*<>(const Mat<Num_T> &m, const Vec<Num_T> &v);
361    /*!
362     * \brief Multiplication of vector \c v and matrix \c m with only one row
363     *
364     * This operator multiplies a column vector \c v times matrix \c m that
365     * consists of only one row. Thus, the result of this operator is
366     * exactly the same as the result of the outer product of two vectors,
367     * i.e.: <tt>outer_product(v, m.get_col(0))</tt>.
368     *
369     * \note This operator is deprecated and might be removed or changed in
370     * future releases of IT++.
371     */
372    friend const Mat<Num_T> operator*<>(const Vec<Num_T> &v,
373                                        const Mat<Num_T> &m);
374    //! Multiplication of matrix and scalar
375    friend const Mat<Num_T> operator*<>(const Mat<Num_T> &m, Num_T t);
376    //! Multiplication of scalar and matrix
377    friend const Mat<Num_T> operator*<>(Num_T t, const Mat<Num_T> &m);
378
379    //! Element wise multiplication of two matrices. Same functionality as Matlab expression A .* B
380    friend const Mat<Num_T> elem_mult <>(const Mat<Num_T> &A, const Mat<Num_T> &B);
381    //! Element wise multiplication of two matrices, storing the result in matrix \c out (which is re-sized if necessary)
382    friend void elem_mult_out <>(const Mat<Num_T> &A, const Mat<Num_T> &B, Mat<Num_T> &out);
383    //! Element wise multiplication of three matrices, storing the result in matrix \c out (which is re-sized if necessary)
384    friend void elem_mult_out <>(const Mat<Num_T> &A, const Mat<Num_T> &B, const Mat<Num_T> &C, Mat<Num_T> &out);
385    //! Element wise multiplication of four matrices, storing the result in matrix \c out (which is re-sized if necessary)
386    friend void elem_mult_out <>(const Mat<Num_T> &A, const Mat<Num_T> &B, const Mat<Num_T> &C, const Mat<Num_T> &D, Mat<Num_T> &out);
387    //! In-place element wise multiplication of two matrices. Fast version of B = elem_mult(A,B)
388    friend void elem_mult_inplace <>(const Mat<Num_T> &A, Mat<Num_T> &B);
389    //! Element wise multiplication of two matrices, followed by summation of the resultant elements. Fast version of sumsum(elem_mult(A,B))
390    friend Num_T elem_mult_sum <>(const Mat<Num_T> &A, const Mat<Num_T> &B);
391
392    //! Division by a scalar
393    Mat<Num_T>& operator/=(Num_T t);
394    //! Division of matrix with scalar
395    friend const Mat<Num_T> operator/<>(const Mat<Num_T> &m, Num_T t);
396    //! Elementwise division with the current matrix
397    Mat<Num_T>& operator/=(const Mat<Num_T> &m);
398
399    //! Element wise division of two matrices. Same functionality as Matlab expression A ./ B
400    friend const Mat<Num_T> elem_div <>(const Mat<Num_T> &A, const Mat<Num_T> &B);
401    //! Element wise division of two matrices, storing the result in matrix \c out (which is re-sized if necessary)
402    friend void elem_div_out <>(const Mat<Num_T> &A, const Mat<Num_T> &B, Mat<Num_T> &out);
403    //! Element wise division of two matrices, followed by summation of the resultant elements. Fast version of sumsum(elem_div(A,B))
404    friend Num_T elem_div_sum <>(const Mat<Num_T> &A, const Mat<Num_T> &B);
405
406    //! Compare two matrices. False if wrong sizes or different values
407    bool operator==(const Mat<Num_T> &m) const;
408    //! Compare two matrices. True if different
409    bool operator!=(const Mat<Num_T> &m) const;
410
411    //! Get element (R,C) from matrix without boundary check (Not recommended to use).
412    Num_T &_elem(int R,int C) { return data[R+C*no_rows]; }
413    //! Get element (R,C) from matrix without boundary check (Not recommended to use).
414    const Num_T &_elem(int R,int C) const { return data[R+C*no_rows]; }
415    //! Get element \c index using linear addressing (by rows) without boundary check (Not recommended to use).
416    Num_T &_elem(int index) { return data[index]; }
417    //! Get element \c index using linear addressing (by rows) without boundary check (Not recommended to use).
418    const Num_T &_elem(int index) const { return data[index]; }
419
420    //! Access of the internal data structure. Don't use. May be changed!
421    Num_T *_data() { return data; }
422    //! Access to the internal data structure. Don't use. May be changed!
423    const Num_T *_data() const { return data; }
424    //! Access to the internal data structure. Don't use. May be changed!
425    int _datasize() const { return datasize; }
426
427  protected:
428    //! Allocate memory for the matrix
429    void alloc(int rows, int cols);
430    //! Free the memory space of the matrix
431    void free();
432
433    /*! Protected integer variables
434     * @{ */
435    int datasize, no_rows, no_cols;
436    /*! @} */
437    //! Protected data pointer
438    Num_T *data;
439    //! Element factory (set to DEFAULT_FACTORY to use Num_T default constructors only)
440    const Factory &factory;
441  };
442
443  // -------------------------------------------------------------------------------------
444  // Type definitions of mat, cmat, imat, smat, and bmat
445  // -------------------------------------------------------------------------------------
446
447  /*!
448    \relates Mat
449    \brief Default Matrix Type
450  */
451  typedef Mat<double> mat;
452
453  /*!
454    \relates Mat
455    \brief Default Complex Matrix Type
456  */
457  typedef Mat<std::complex<double> > cmat;
458
459  /*!
460    \relates Mat
461    \brief Integer matrix
462  */
463  typedef Mat<int> imat;
464
465  /*!
466    \relates Mat
467    \brief short int matrix
468  */
469  typedef Mat<short int> smat;
470
471  /*!
472    \relates Mat
473    \relates GF2mat
474    \relates GF2mat_sparse
475    \brief bin matrix
476  */
477  typedef Mat<bin> bmat;
478
479} //namespace itpp
480
481
482#include <itpp/base/vec.h>
483
484namespace itpp {
485
486  // ----------------------------------------------------------------------
487  // Declaration of input and output streams for Mat
488  // ----------------------------------------------------------------------
489
490  /*!
491    \relatesalso Mat
492    \brief Output stream for matrices
493  */
494  template <class Num_T>
495  std::ostream &operator<<(std::ostream &os, const Mat<Num_T> &m);
496
497  /*!
498    \relatesalso Mat
499    \brief Input stream for matrices
500
501    The input can be on the form "1 2 3; 4 5 6" or "[[1 2 3][4 5 6]]", i.e. with
502    brackets or semicolons as row delimiters. The first form is compatible with
503    the set method, while the second form is compatible with the ostream
504    operator. The elements on a row can be separated by blank space or commas.
505    Rows that are shorter than the longest row are padded with zero elements.
506    "[]" means an empty matrix.
507  */
508  template <class Num_T>
509  std::istream &operator>>(std::istream &is, Mat<Num_T> &m);
510
511  // ----------------------------------------------------------------------
512  // Implementation of templated Mat members and friends
513  // ----------------------------------------------------------------------
514
515  template<class Num_T> inline
516  void Mat<Num_T>::alloc(int rows, int cols)
517  {
518    if ((rows > 0) && (cols > 0)) {
519      datasize = rows * cols;
520      no_rows = rows;
521      no_cols = cols;
522      create_elements(data, datasize, factory);
523    }
524    else {
525      data = 0;
526      datasize = 0;
527      no_rows = 0;
528      no_cols = 0;
529    }
530  }
531
532  template<class Num_T> inline
533  void Mat<Num_T>::free()
534  {
535    destroy_elements(data, datasize);
536    datasize = 0;
537    no_rows = 0;
538    no_cols = 0;
539  }
540
541
542  template<class Num_T> inline
543  Mat<Num_T>::Mat(const Factory &f) :
544    datasize(0), no_rows(0), no_cols(0), data(0), factory(f) {}
545
546  template<class Num_T> inline
547  Mat<Num_T>::Mat(int inrow, int incol, const Factory &f) :
548    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
549  {
550    it_assert_debug((inrow >= 0) && (incol >= 0), "The rows and columns must be >= 0");
551    alloc(inrow, incol);
552  }
553
554  template<class Num_T> inline
555  Mat<Num_T>::Mat(const Mat<Num_T> &m) :
556    datasize(0), no_rows(0), no_cols(0), data(0), factory(m.factory)
557  {
558    alloc(m.no_rows, m.no_cols);
559    copy_vector(m.datasize, m.data, data);
560  }
561
562  template<class Num_T> inline
563  Mat<Num_T>::Mat(const Mat<Num_T> &m, const Factory &f) :
564    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
565  {
566    alloc(m.no_rows, m.no_cols);
567    copy_vector(m.datasize, m.data, data);
568  }
569
570  template<class Num_T> inline
571  Mat<Num_T>::Mat(const Vec<Num_T> &invector, const Factory &f) :
572    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
573  {
574    int size = invector.size();
575    alloc(size, 1);
576    copy_vector(size, invector._data(), data);
577  }
578
579  template<class Num_T> inline
580  Mat<Num_T>::Mat(const std::string &str, const Factory &f) :
581    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
582  {
583    set(str);
584  }
585
586  template<class Num_T> inline
587  Mat<Num_T>::Mat(const char *str, const Factory &f) :
588    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
589  {
590    set(str);
591  }
592
593  template<class Num_T> inline
594  Mat<Num_T>::Mat(const Num_T *c_array, int rows, int cols, bool RowMajor, const Factory &f) :
595    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
596  {
597    alloc(rows, cols);
598
599    if (!RowMajor)
600      copy_vector(datasize, c_array, data);
601    else { // Row Major
602      for (int i=0; i<rows; i++) {
603        for (int j=0; j<cols; j++)
604          data[i+j*no_rows] = c_array[i*no_cols+j];
605      }
606    }
607  }
608
609  template<class Num_T> inline
610  Mat<Num_T>::~Mat()
611  {
612    free();
613  }
614
615
616  template<class Num_T>
617  void Mat<Num_T>::set_size(int inrow, int incol, bool copy)
618  {
619    it_assert_debug((inrow >= 0) && (incol >= 0), "Mat<Num_T>::set_size: "
620                    "The number of rows and columns must be >= 0");
621    // check if we have to resize the current matrix
622    if ((no_rows == inrow) && (no_cols == incol))
623      return;
624    // conditionally copy previous matrix content
625    if (copy) {
626      // create a temporary pointer to the allocated data
627      Num_T* tmp = data;
628      // store the current number of elements and number of rows
629      int old_datasize = datasize;
630      int old_rows = no_rows;
631      // check the boundaries of the copied data
632      int min_r = (no_rows < inrow) ? no_rows : inrow;
633      int min_c = (no_cols < incol) ? no_cols : incol;
634      // allocate new memory
635      alloc(inrow, incol);
636      // copy the previous data into the allocated memory
637      for (int i = 0; i < min_c; ++i) {
638        copy_vector(min_r, &tmp[i*old_rows], &data[i*no_rows]);
639      }
640      // fill-in the rest of matrix with zeros
641      for (int i = min_r; i < inrow; ++i)
642        for (int j = 0; j < incol; ++j)
643          data[i+j*inrow] = Num_T(0);
644      for (int j = min_c; j < incol; ++j)
645        for (int i = 0; i < min_r; ++i)
646          data[i+j*inrow] = Num_T(0);
647      // delete old elements
648      destroy_elements(tmp, old_datasize);
649    }
650    // if possible, reuse the allocated memory
651    else if (datasize == inrow * incol) {
652      no_rows = inrow;
653      no_cols = incol;
654    }
655    // finally release old memory and allocate a new one
656    else {
657      free();
658      alloc(inrow, incol);
659    }
660  }
661
662  template<class Num_T> inline
663  void Mat<Num_T>::zeros()
664  {
665    for(int i=0; i<datasize; i++)
666      data[i] = Num_T(0);
667  }
668
669  template<class Num_T> inline
670  void Mat<Num_T>::ones()
671  {
672    for(int i=0; i<datasize; i++)
673      data[i] = Num_T(1);
674  }
675
676  template<class Num_T> inline
677  const Num_T& Mat<Num_T>::operator()(int R,int C) const
678  {
679    it_assert_debug((R >= 0) && (R < no_rows) && (C >= 0) && (C < no_cols),
680               "Mat<Num_T>::operator(): index out of range");
681    return data[R+C*no_rows];
682  }
683
684  template<class Num_T> inline
685  Num_T& Mat<Num_T>::operator()(int R,int C)
686  {
687    it_assert_debug((R >= 0) && (R < no_rows) && (C >= 0) && (C < no_cols),
688               "Mat<Num_T>::operator(): index out of range");
689    return data[R+C*no_rows];
690  }
691
692  template<class Num_T> inline
693  Num_T& Mat<Num_T>::operator()(int index)
694  {
695    it_assert_debug((index < no_rows*no_cols) && (index >= 0),
696               "Mat<Num_T>::operator(): index out of range");
697    return data[index];
698  }
699
700  template<class Num_T> inline
701  const Num_T& Mat<Num_T>::operator()(int index) const
702  {
703    it_assert_debug((index < no_rows*no_cols) && (index >= 0),
704               "Mat<Num_T>::operator(): index out of range");
705    return data[index];
706  }
707
708  template<class Num_T> inline
709  const Num_T& Mat<Num_T>::get(int R,int C) const
710  {
711    it_assert_debug((R >= 0) && (R < no_rows) && (C >= 0) && (C < no_cols),
712               "Mat<Num_T>::get(): index out of range");
713    return data[R+C*no_rows];
714  }
715
716  template<class Num_T> inline
717  void Mat<Num_T>::set(int R, int C, const Num_T &v)
718  {
719    it_assert_debug((R >= 0) && (R < no_rows) && (C >= 0) && (C < no_cols),
720               "Mat<Num_T>::set(): index out of range");
721    data[R+C*no_rows] = v;
722  }
723
724
725  template<class Num_T>
726  void Mat<Num_T>::set(const std::string &str)
727  {
728    // actual row counter
729    int rows = 0;
730    // number of rows to allocate next time (8, 16, 32, 64, etc.)
731    int maxrows = 8;
732
733    // clean the current matrix content
734    free();
735
736    // variable to store the start of a current vector
737    std::string::size_type beg = 0;
738    std::string::size_type end = 0;
739    while (end != std::string::npos) {
740      // find next occurence of a semicolon in string str
741      end = str.find(';', beg);
742      // parse first row into a vector v
743      Vec<Num_T> v(str.substr(beg, end-beg));
744      int v_size = v.size();
745
746      // this check is necessary to parse the following two strings as the
747      // same matrix: "1 0 1; ; 1 1; " and "1 0 1; 0 0 0; 1 1 0"
748      if ((end != std::string::npos) || (v_size > 0)) {
749        // matrix empty -> insert v as a first row and allocate maxrows
750        if (rows == 0) {
751          set_size(maxrows, v_size, true);
752          set_row(rows++, v);
753        }
754        else {
755          // check if we need to resize the matrix
756          if ((rows == maxrows) || (v_size != no_cols)) {
757            // we need to add new rows
758            if (rows == maxrows) {
759              maxrows *= 2;
760            }
761            // check if ne need to add new colums
762            if (v_size > no_cols) {
763              set_size(maxrows, v_size, true);
764            }
765            else {
766              set_size(maxrows, no_cols, true);
767              // set the size of the parsed vector to the number of colums
768              v.set_size(no_cols, true);
769            }
770          }
771          // set the parsed vector as the next row
772          set_row(rows++, v);
773        }
774      }
775      // update the starting position of the next vector in the parsed
776      // string
777      beg = end + 1;
778    } // if ((end != std::string::npos) || (v.size > 0))
779
780    set_size(rows, no_cols, true);
781  }
782
783  template<class Num_T>
784  void Mat<Num_T>::set(const char *str)
785  {
786    set(std::string(str));
787  }
788
789  template<class Num_T> inline
790  const Mat<Num_T> Mat<Num_T>::operator()(int r1, int r2, int c1, int c2) const
791  {
792    if (r1 == -1) r1 = no_rows-1;
793    if (r2 == -1) r2 = no_rows-1;
794    if (c1 == -1) c1 = no_cols-1;
795    if (c2 == -1) c2 = no_cols-1;
796
797    it_assert_debug(r1>=0 && r2>=0 && r1<no_rows && r2<no_rows &&
798               c1>=0 && c2>=0 && c1<no_cols && c2<no_cols, "operator()(r1,r2,c1,c2)");
799
800    it_assert_debug(r2>=r1 && c2>=c1, "Mat<Num_T>::op(): r2>=r1 or c2>=c1 not fulfilled");
801
802    Mat<Num_T> s(r2-r1+1, c2-c1+1);
803
804    for (int i=0;i<s.no_cols;i++)
805      copy_vector(s.no_rows, data+r1+(c1+i)*no_rows, s.data+i*s.no_rows);
806
807    return s;
808  }
809
810  template<class Num_T> inline
811  const Mat<Num_T> Mat<Num_T>::get(int r1, int r2, int c1, int c2) const
812  {
813    return (*this)(r1, r2, c1, c2);
814  }
815
816  template<class Num_T> inline
817  const Vec<Num_T> Mat<Num_T>::get_row(int Index) const
818  {
819    it_assert_debug(Index>=0 && Index<no_rows, "Mat<Num_T>::get_row: index out of range");
820    Vec<Num_T> a(no_cols);
821
822    copy_vector(no_cols, data+Index, no_rows, a._data(), 1);
823    return a;
824  }
825
826  template<class Num_T>
827  const Mat<Num_T> Mat<Num_T>::get_rows(int r1, int r2) const
828  {
829    it_assert_debug(r1>=0 && r2<no_rows && r1<=r2, "Mat<Num_T>::get_rows: index out of range");
830    Mat<Num_T> m(r2-r1+1, no_cols);
831
832    for (int i=0; i<m.rows(); i++)
833      copy_vector(no_cols, data+i+r1, no_rows, m.data+i, m.no_rows);
834
835    return m;
836  }
837
838  template<class Num_T>
839  const Mat<Num_T> Mat<Num_T>::get_rows(const Vec<int> &indexlist) const
840  {
841    Mat<Num_T> m(indexlist.size(),no_cols);
842
843    for (int i=0;i<indexlist.size();i++) {
844      it_assert_debug(indexlist(i)>=0 && indexlist(i)<no_rows, "Mat<Num_T>::get_rows: index out of range");
845      copy_vector(no_cols, data+indexlist(i), no_rows, m.data+i, m.no_rows);
846    }
847
848    return m;
849  }
850
851  template<class Num_T> inline
852  const Vec<Num_T> Mat<Num_T>::get_col(int Index) const
853  {
854    it_assert_debug(Index>=0 && Index<no_cols, "Mat<Num_T>::get_col: index out of range");
855    Vec<Num_T> a(no_rows);
856
857    copy_vector(no_rows, data+Index*no_rows, a._data());
858
859    return a;
860  }
861
862  template<class Num_T> inline
863  const Mat<Num_T> Mat<Num_T>::get_cols(int c1, int c2) const
864  {
865    it_assert_debug(c1>=0 && c2<no_cols && c1<=c2, "Mat<Num_T>::get_cols: index out of range");
866    Mat<Num_T> m(no_rows, c2-c1+1);
867
868    for (int i=0; i<m.cols(); i++)
869      copy_vector(no_rows, data+(i+c1)*no_rows, m.data+i*m.no_rows);
870
871    return m;
872  }
873
874  template<class Num_T> inline
875  const Mat<Num_T> Mat<Num_T>::get_cols(const Vec<int> &indexlist) const
876  {
877    Mat<Num_T> m(no_rows,indexlist.size());
878
879    for (int i=0; i<indexlist.size(); i++) {
880      it_assert_debug(indexlist(i)>=0 && indexlist(i)<no_cols, "Mat<Num_T>::get_cols: index out of range");
881      copy_vector(no_rows, data+indexlist(i)*no_rows, m.data+i*m.no_rows);
882    }
883
884    return m;
885  }
886
887  template<class Num_T> inline
888  void Mat<Num_T>::set_row(int Index, const Vec<Num_T> &v)
889  {
890    it_assert_debug(Index>=0 && Index<no_rows, "Mat<Num_T>::set_row: index out of range");
891    it_assert_debug(v.length() == no_cols, "Mat<Num_T>::set_row: lengths doesn't match");
892
893    copy_vector(v.size(), v._data(), 1, data+Index, no_rows);
894  }
895
896  template<class Num_T> inline
897  void Mat<Num_T>::set_col(int Index, const Vec<Num_T> &v)
898  {
899    it_assert_debug(Index>=0 && Index<no_cols, "Mat<Num_T>::set_col: index out of range");
900    it_assert_debug(v.length() == no_rows, "Mat<Num_T>::set_col: lengths doesn't match");
901
902    copy_vector(v.size(), v._data(), data+Index*no_rows);
903  }
904
905
906  template<class Num_T> inline
907  void Mat<Num_T>::set_rows(int r, const Mat<Num_T> &m)
908  {
909    it_assert_debug((r >= 0) && (r < no_rows),
910                    "Mat<>::set_rows(): Index out of range");
911    it_assert_debug(no_cols == m.cols(),
912                    "Mat<>::set_rows(): Column sizes do not match");
913    it_assert_debug(m.rows() + r <= no_rows,
914                    "Mat<>::set_rows(): Not enough rows");
915
916    for (int i = 0; i < m.rows(); ++i) {
917      copy_vector(no_cols, m.data+i, m.no_rows, data+i+r, no_rows);
918    }
919  }
920
921  template<class Num_T> inline
922  void Mat<Num_T>::set_cols(int c, const Mat<Num_T> &m)
923  {
924    it_assert_debug((c >= 0) && (c < no_cols),
925                    "Mat<>::set_cols(): Index out of range");
926    it_assert_debug(no_rows == m.rows(),
927                    "Mat<>::set_cols(): Row sizes do not match");
928    it_assert_debug(m.cols() + c <= no_cols,
929                    "Mat<>::set_cols(): Not enough colums");
930
931    for (int i = 0; i < m.cols(); ++i) {
932      copy_vector(no_rows, m.data+i*no_rows, data+(i+c)*no_rows);
933    }
934  }
935
936
937  template<class Num_T> inline
938  void Mat<Num_T>::copy_row(int to, int from)
939  {
940    it_assert_debug(to>=0 && from>=0 && to<no_rows && from<no_rows,
941               "Mat<Num_T>::copy_row: index out of range");
942
943    if (from == to)
944      return;
945
946    copy_vector(no_cols, data+from, no_rows, data+to, no_rows);
947  }
948
949  template<class Num_T> inline
950  void Mat<Num_T>::copy_col(int to, int from)
951  {
952    it_assert_debug(to>=0 && from>=0 && to<no_cols && from<no_cols,
953               "Mat<Num_T>::copy_col: index out of range");
954
955    if (from == to)
956      return;
957
958    copy_vector(no_rows, data+from*no_rows, data+to*no_rows);
959  }
960
961  template<class Num_T> inline
962  void Mat<Num_T>::swap_rows(int r1, int r2)
963  {
964    it_assert_debug(r1>=0 && r2>=0 && r1<no_rows && r2<no_rows,
965               "Mat<Num_T>::swap_rows: index out of range");
966
967    if (r1 == r2)
968      return;
969
970    swap_vector(no_cols, data+r1, no_rows, data+r2, no_rows);
971  }
972
973  template<class Num_T> inline
974  void Mat<Num_T>::swap_cols(int c1, int c2)
975  {
976    it_assert_debug(c1>=0 && c2>=0 && c1<no_cols && c2<no_cols,
977               "Mat<Num_T>::swap_cols: index out of range");
978
979    if (c1 == c2)
980      return;
981
982    swap_vector(no_rows, data+c1*no_rows, data+c2*no_rows);
983  }
984
985  template<class Num_T> inline
986  void Mat<Num_T>::set_submatrix(int r1, int r2, int c1, int c2, const Mat<Num_T> &m)
987  {
988
989    if (r1 == -1) r1 = no_rows-1;
990    if (r2 == -1) r2 = no_rows-1;
991    if (c1 == -1) c1 = no_cols-1;
992    if (c2 == -1) c2 = no_cols-1;
993
994    it_assert_debug(r1>=0 && r2>=0 && r1<no_rows && r2<no_rows &&
995               c1>=0 && c2>=0 && c1<no_cols && c2<no_cols, "Mat<Num_T>::set_submatrix(): index out of range");
996
997    it_assert_debug(r2>=r1 && c2>=c1, "Mat<Num_T>::set_submatrix: r2<r1 or c2<c1");
998    it_assert_debug(m.no_rows == r2-r1+1 && m.no_cols == c2-c1+1, "Mat<Num_T>::set_submatrix(): sizes don't match");
999
1000    for (int i=0; i<m.no_cols; i++)
1001      copy_vector(m.no_rows, m.data+i*m.no_rows, data+(c1+i)*no_rows+r1);
1002  }
1003
1004
1005
1006  template<class Num_T> inline
1007  void Mat<Num_T>::set_submatrix(int r, int c, const Mat<Num_T> &m)
1008  {
1009
1010    it_assert_debug(r>=0 && r+m.no_rows<=no_rows &&
1011               c>=0 && c+m.no_cols<=no_cols, "Mat<Num_T>::set_submatrix(): index out of range");
1012
1013    for (int i=0; i<m.no_cols; i++)
1014      copy_vector(m.no_rows, m.data+i*m.no_rows, data+(c+i)*no_rows+r);
1015  }
1016
1017
1018
1019  template<class Num_T> inline
1020  void Mat<Num_T>::set_submatrix(int r1, int r2, int c1, int c2, const Num_T t)
1021  {
1022
1023    if (r1 == -1) r1 = no_rows-1;
1024    if (r2 == -1) r2 = no_rows-1;
1025    if (c1 == -1) c1 = no_cols-1;
1026    if (c2 == -1) c2 = no_cols-1;
1027
1028    it_assert_debug(r1>=0 && r2>=0 && r1<no_rows && r2<no_rows &&
1029               c1>=0 && c2>=0 && c1<no_cols && c2<no_cols, "Mat<Num_T>::set_submatrix(): index out of range");
1030
1031    it_assert_debug(r2>=r1 && c2>=c1, "Mat<Num_T>::set_submatrix: r2<r1 or c2<c1");
1032
1033    int i, j, pos, rows = r2-r1+1;
1034
1035    for (i=c1; i<=c2; i++) {
1036      pos = i*no_rows+r1;
1037      for (j=0; j<rows; j++) {
1038        data[pos++] = t;
1039      }
1040    }
1041  }
1042
1043  template<class Num_T> inline
1044  void Mat<Num_T>::del_row(int r)
1045  {
1046    it_assert_debug(r>=0 && r<no_rows, "Mat<Num_T>::del_row(): index out of range");
1047    Mat<Num_T> Temp(*this);
1048    set_size(no_rows-1, no_cols, false);
1049    for (int i=0 ; i < r ; i++) {
1050      copy_vector(no_cols, &Temp.data[i], no_rows+1, &data[i], no_rows);
1051    }
1052    for (int i=r ; i < no_rows ; i++) {
1053      copy_vector(no_cols, &Temp.data[i+1], no_rows+1, &data[i], no_rows);
1054    }
1055
1056  }
1057
1058  template<class Num_T> inline
1059  void Mat<Num_T>::del_rows(int r1, int r2)
1060  {
1061    it_assert_debug((r1 >= 0) && (r2 < no_rows) && (r1 <= r2),
1062                    "Mat<Num_T>::del_rows(): indices out of range");
1063
1064    Mat<Num_T> Temp(*this);
1065    int no_del_rows = r2-r1+1;
1066    set_size(no_rows-no_del_rows, no_cols, false);
1067    for (int i = 0; i < r1 ; ++i) {
1068      copy_vector(no_cols, &Temp.data[i], Temp.no_rows, &data[i], no_rows);
1069    }
1070    for (int i = r2+1; i < Temp.no_rows; ++i) {
1071      copy_vector(no_cols, &Temp.data[i], Temp.no_rows, &data[i-no_del_rows],
1072                  no_rows);
1073    }
1074  }
1075
1076  template<class Num_T> inline
1077  void Mat<Num_T>::del_col(int c)
1078  {
1079    it_assert_debug(c>=0 && c<no_cols, "Mat<Num_T>::del_col(): index out of range");
1080    Mat<Num_T> Temp(*this);
1081
1082    set_size(no_rows, no_cols-1, false);
1083    copy_vector(c*no_rows, Temp.data, data);
1084    copy_vector((no_cols - c)*no_rows, &Temp.data[(c+1)*no_rows], &data[c*no_rows]);
1085  }
1086
1087  template<class Num_T> inline
1088  void Mat<Num_T>::del_cols(int c1, int c2)
1089  {
1090    it_assert_debug(c1>=0 && c2<no_cols && c1<=c2, "Mat<Num_T>::del_cols(): index out of range");
1091    Mat<Num_T> Temp(*this);
1092    int n_deleted_cols = c2-c1+1;
1093    set_size(no_rows, no_cols-n_deleted_cols, false);
1094    copy_vector(c1*no_rows, Temp.data, data);
1095    copy_vector((no_cols-c1)*no_rows, &Temp.data[(c2+1)*no_rows], &data[c1*no_rows]);
1096  }
1097
1098  template<class Num_T> inline
1099  void Mat<Num_T>::ins_row(int r, const Vec<Num_T> &in)
1100  {
1101    it_assert_debug(r>=0 && r<=no_rows, "Mat<Num_T>::ins_row(): index out of range");
1102    it_assert_debug((in.size() == no_cols) || no_rows==0, "Mat<Num_T>::ins_row(): vector size does not match");
1103
1104    if (no_cols==0) {
1105      no_cols = in.size();
1106    }
1107
1108    Mat<Num_T> Temp(*this);
1109    set_size(no_rows+1, no_cols, false);
1110
1111    for (int i=0 ; i < r ; i++) {
1112      copy_vector(no_cols, &Temp.data[i], no_rows-1, &data[i], no_rows);
1113    }
1114    copy_vector(no_cols, in._data(), 1, &data[r], no_rows);
1115    for (int i=r+1 ; i < no_rows ; i++) {
1116      copy_vector(no_cols, &Temp.data[i-1], no_rows-1, &data[i], no_rows);
1117    }
1118  }
1119
1120  template<class Num_T> inline
1121  void Mat<Num_T>::ins_col(int c, const Vec<Num_T> &in)
1122  {
1123    it_assert_debug(c>=0 && c<=no_cols, "Mat<Num_T>::ins_col(): index out of range");
1124    it_assert_debug(in.size() == no_rows || no_cols==0, "Mat<Num_T>::ins_col(): vector size does not match");
1125
1126    if (no_rows==0) {
1127      no_rows = in.size();
1128    }
1129
1130    Mat<Num_T> Temp(*this);
1131    set_size(no_rows, no_cols+1, false);
1132
1133    copy_vector(c*no_rows, Temp.data, data);
1134    copy_vector(no_rows, in._data(), &data[c*no_rows]);
1135    copy_vector((no_cols-c-1)*no_rows, &Temp.data[c*no_rows], &data[(c+1)*no_rows]);
1136  }
1137
1138  template<class Num_T> inline
1139  void Mat<Num_T>::append_row(const Vec<Num_T> &in)
1140  {
1141    ins_row(no_rows, in);
1142  }
1143
1144  template<class Num_T> inline
1145  void Mat<Num_T>::append_col(const Vec<Num_T> &in)
1146  {
1147    ins_col(no_cols, in);
1148  }
1149
1150  template<class Num_T>
1151  const Mat<Num_T> Mat<Num_T>::transpose() const
1152  {
1153    Mat<Num_T> temp(no_cols, no_rows);
1154    for (int i = 0; i < no_rows; ++i) {
1155      copy_vector(no_cols, &data[i], no_rows, &temp.data[i * no_cols], 1);
1156    }
1157    return temp;
1158  }
1159
1160  //! \cond
1161  template<>
1162  const cmat Mat<std::complex<double> >::hermitian_transpose() const;
1163  //! \endcond
1164
1165  template<class Num_T>
1166  const Mat<Num_T> Mat<Num_T>::hermitian_transpose() const
1167  {
1168    Mat<Num_T> temp(no_cols, no_rows);
1169    for (int i = 0; i < no_rows; ++i) {
1170      copy_vector(no_cols, &data[i], no_rows, &temp.data[i * no_cols], 1);
1171    }
1172    return temp;
1173  }
1174
1175  template<class Num_T>
1176  const Mat<Num_T> concat_horizontal(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
1177  {
1178    it_assert_debug(m1.no_rows == m2.no_rows,
1179                    "Mat<Num_T>::concat_horizontal(): wrong sizes");
1180    int no_rows = m1.no_rows;
1181    Mat<Num_T> temp(no_rows, m1.no_cols + m2.no_cols);
1182    for (int i = 0; i < m1.no_cols; ++i) {
1183      copy_vector(no_rows, &m1.data[i * no_rows], &temp.data[i * no_rows]);
1184    }
1185    for (int i = 0; i < m2.no_cols; ++i) {
1186      copy_vector(no_rows, &m2.data[i * no_rows], &temp.data[(m1.no_cols + i)
1187                                                             * no_rows]);
1188    }
1189    return temp;
1190  }
1191
1192  template<class Num_T>
1193  const Mat<Num_T> concat_vertical(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
1194  {
1195    it_assert_debug(m1.no_cols == m2.no_cols,
1196                    "Mat<Num_T>::concat_vertical; wrong sizes");
1197    int no_cols = m1.no_cols;
1198    Mat<Num_T> temp(m1.no_rows + m2.no_rows, no_cols);
1199    for (int i = 0; i < no_cols; ++i) {
1200      copy_vector(m1.no_rows, &m1.data[i * m1.no_rows],
1201                  &temp.data[i * temp.no_rows]);
1202      copy_vector(m2.no_rows, &m2.data[i * m2.no_rows],
1203                  &temp.data[i * temp.no_rows + m1.no_rows]);
1204    }
1205    return temp;
1206  }
1207
1208  template<class Num_T> inline
1209  Mat<Num_T>& Mat<Num_T>::operator=(Num_T t)
1210  {
1211    for (int i=0; i<datasize; i++)
1212      data[i] = t;
1213    return *this;
1214  }
1215
1216  template<class Num_T> inline
1217  Mat<Num_T>& Mat<Num_T>::operator=(const Mat<Num_T> &m)
1218  {
1219    if (this != &m) {
1220      set_size(m.no_rows,m.no_cols, false);
1221      if (m.datasize != 0)
1222        copy_vector(m.datasize, m.data, data);
1223    }
1224    return *this;
1225  }
1226
1227  template<class Num_T> inline
1228  Mat<Num_T>& Mat<Num_T>::operator=(const Vec<Num_T> &v)
1229  {
1230    it_assert_debug((no_rows == 1 && no_cols == v.size())
1231                    || (no_cols == 1 && no_rows == v.size()),
1232                    "Mat<Num_T>::operator=(): Wrong size of the argument");
1233    set_size(v.size(), 1, false);
1234    copy_vector(v.size(), v._data(), data);
1235    return *this;
1236  }
1237
1238  template<class Num_T> inline
1239  Mat<Num_T>& Mat<Num_T>::operator=(const char *values)
1240  {
1241    set(values);
1242    return *this;
1243  }
1244
1245  //-------------------- Templated friend functions --------------------------
1246
1247  template<class Num_T> inline
1248  Mat<Num_T>& Mat<Num_T>::operator+=(const Mat<Num_T> &m)
1249  {
1250    if (datasize == 0)
1251      operator=(m);
1252    else {
1253      int i, j, m_pos=0, pos=0;
1254      it_assert_debug(m.no_rows==no_rows && m.no_cols==no_cols,"Mat<Num_T>::operator+=: wrong sizes");
1255      for (i=0; i<no_cols; i++) {
1256        for (j=0; j<no_rows; j++)
1257          data[pos+j] += m.data[m_pos+j];
1258        pos += no_rows;
1259        m_pos += m.no_rows;
1260      }
1261    }
1262    return *this;
1263  }
1264
1265  template<class Num_T> inline
1266  Mat<Num_T>& Mat<Num_T>::operator+=(Num_T t)
1267  {
1268    for (int i=0; i<datasize; i++)
1269      data[i] += t;
1270    return *this;
1271  }
1272
1273  template<class Num_T> inline
1274  const Mat<Num_T> operator+(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
1275  {
1276    Mat<Num_T> r(m1.no_rows, m1.no_cols);
1277    int i, j, m1_pos=0, m2_pos=0, r_pos=0;
1278
1279    it_assert_debug(m1.no_rows==m2.no_rows && m1.no_cols == m2.no_cols, "Mat<Num_T>::operator+: wrong sizes");
1280
1281    for (i=0; i<r.no_cols; i++) {
1282      for (j=0; j<r.no_rows; j++)
1283        r.data[r_pos+j] = m1.data[m1_pos+j] + m2.data[m2_pos+j];
1284      // next column
1285      m1_pos += m1.no_rows;
1286      m2_pos += m2.no_rows;
1287      r_pos += r.no_rows;
1288    }
1289
1290    return r;
1291  }
1292
1293
1294  template<class Num_T> inline
1295  const Mat<Num_T> operator+(const Mat<Num_T> &m, Num_T t)
1296  {
1297    Mat<Num_T> r(m.no_rows, m.no_cols);
1298
1299    for (int i=0; i<r.datasize; i++)
1300      r.data[i] = m.data[i] + t;
1301
1302    return r;
1303  }
1304
1305  template<class Num_T> inline
1306  const Mat<Num_T> operator+(Num_T t, const Mat<Num_T> &m)
1307  {
1308    Mat<Num_T> r(m.no_rows, m.no_cols);
1309
1310    for (int i=0; i<r.datasize; i++)
1311      r.data[i] = t + m.data[i];
1312
1313    return r;
1314  }
1315
1316  template<class Num_T> inline
1317  Mat<Num_T>& Mat<Num_T>::operator-=(const Mat<Num_T> &m)
1318  {
1319    int i,j, m_pos=0, pos=0;
1320
1321    if (datasize == 0) {
1322      set_size(m.no_rows, m.no_cols, false);
1323      for (i=0; i<no_cols; i++) {
1324        for (j=0; j<no_rows; j++)
1325          data[pos+j] = -m.data[m_pos+j];
1326        // next column
1327        m_pos += m.no_rows;
1328        pos += no_rows;
1329      }
1330    } else {
1331      it_assert_debug(m.no_rows==no_rows && m.no_cols==no_cols,"Mat<Num_T>::operator-=: wrong sizes");
1332      for (i=0; i<no_cols; i++) {
1333        for (j=0; j<no_rows; j++)
1334          data[pos+j] -= m.data[m_pos+j];
1335        // next column
1336        m_pos += m.no_rows;
1337        pos += no_rows;
1338      }
1339    }
1340    return *this;
1341  }
1342
1343  template<class Num_T> inline
1344  const Mat<Num_T> operator-(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
1345  {
1346    Mat<Num_T> r(m1.no_rows, m1.no_cols);
1347    int i, j, m1_pos=0, m2_pos=0, r_pos=0;
1348
1349    it_assert_debug(m1.no_rows==m2.no_rows && m1.no_cols == m2.no_cols, "Mat<Num_T>::operator-: wrong sizes");
1350
1351    for (i=0; i<r.no_cols; i++) {
1352      for (j=0; j<r.no_rows; j++)
1353        r.data[r_pos+j] = m1.data[m1_pos+j] - m2.data[m2_pos+j];
1354      // next column
1355      m1_pos += m1.no_rows;
1356      m2_pos += m2.no_rows;
1357      r_pos += r.no_rows;
1358    }
1359
1360    return r;
1361  }
1362
1363  template<class Num_T> inline
1364  Mat<Num_T>& Mat<Num_T>::operator-=(Num_T t)
1365  {
1366    for (int i=0; i<datasize; i++)
1367      data[i] -= t;
1368    return *this;
1369  }
1370
1371  template<class Num_T> inline
1372  const Mat<Num_T> operator-(const Mat<Num_T> &m, Num_T t)
1373  {
1374    Mat<Num_T> r(m.no_rows, m.no_cols);
1375    int i, j, m_pos=0, r_pos=0;
1376
1377    for (i=0; i<r.no_cols; i++) {
1378      for (j=0; j<r.no_rows; j++)
1379        r.data[r_pos+j] = m.data[m_pos+j] - t;
1380      // next column
1381      m_pos += m.no_rows;
1382      r_pos += r.no_rows;
1383    }
1384
1385    return r;
1386  }
1387
1388  template<class Num_T> inline
1389  const Mat<Num_T> operator-(Num_T t, const Mat<Num_T> &m)
1390  {
1391    Mat<Num_T> r(m.no_rows, m.no_cols);
1392    int i, j, m_pos=0, r_pos=0;
1393
1394    for (i=0; i<r.no_cols; i++) {
1395      for (j=0; j<r.no_rows; j++)
1396        r.data[r_pos+j] = t - m.data[m_pos+j];
1397      // next column
1398      m_pos += m.no_rows;
1399      r_pos += r.no_rows;
1400    }
1401
1402    return r;
1403  }
1404
1405  template<class Num_T> inline
1406  const Mat<Num_T> operator-(const Mat<Num_T> &m)
1407  {
1408    Mat<Num_T> r(m.no_rows, m.no_cols);
1409    int i, j, m_pos=0, r_pos=0;
1410
1411    for (i=0; i<r.no_cols; i++) {
1412      for (j=0; j<r.no_rows; j++)
1413        r.data[r_pos+j] = -m.data[m_pos+j];
1414      // next column
1415      m_pos += m.no_rows;
1416      r_pos += r.no_rows;
1417    }
1418
1419    return r;
1420  }
1421
1422#if defined(HAVE_BLAS)
1423  template<> mat& Mat<double>::operator*=(const mat &m);
1424  template<> cmat& Mat<std::complex<double> >::operator*=(const cmat &m);
1425#endif
1426
1427  template<class Num_T> inline
1428  Mat<Num_T>& Mat<Num_T>::operator*=(const Mat<Num_T> &m)
1429  {
1430    it_assert_debug(no_cols == m.no_rows,"Mat<Num_T>::operator*=: wrong sizes");
1431    Mat<Num_T> r(no_rows, m.no_cols);
1432
1433    Num_T tmp;
1434
1435    int i,j,k, r_pos=0, pos=0, m_pos=0;
1436
1437    for (i=0; i<r.no_cols; i++) {
1438      for (j=0; j<r.no_rows; j++) {
1439        tmp = Num_T(0);
1440        pos = 0;
1441        for (k=0; k<no_cols; k++) {
1442          tmp += data[pos+j] * m.data[m_pos+k];
1443          pos += no_rows;
1444        }
1445        r.data[r_pos+j] = tmp;
1446      }
1447      r_pos += r.no_rows;
1448      m_pos += m.no_rows;
1449    }
1450    operator=(r); // time consuming
1451    return *this;
1452  }
1453
1454  template<class Num_T> inline
1455  Mat<Num_T>& Mat<Num_T>::operator*=(Num_T t)
1456  {
1457    scal_vector(datasize, t, data);
1458    return *this;
1459  }
1460
1461#if defined(HAVE_BLAS)
1462  template<> const mat operator*(const mat &m1, const mat &m2);
1463  template<> const cmat operator*(const cmat &m1, const cmat &m2);
1464#endif
1465
1466
1467  template<class Num_T>
1468  const Mat<Num_T> operator*(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
1469  {
1470    it_assert_debug(m1.no_cols == m2.no_rows,"Mat<Num_T>::operator*: wrong sizes");
1471    Mat<Num_T> r(m1.no_rows, m2.no_cols);
1472
1473    Num_T tmp;
1474    int i, j, k;
1475    Num_T *tr=r.data, *t1, *t2=m2.data;
1476
1477    for (i=0; i<r.no_cols; i++) {
1478      for (j=0; j<r.no_rows; j++) {
1479        tmp = Num_T(0); t1 = m1.data+j;
1480        for (k=m1.no_cols; k>0; k--) {
1481          tmp += *(t1) * *(t2++);
1482          t1 += m1.no_rows;
1483        }
1484        *(tr++) = tmp; t2 -= m2.no_rows;
1485      }
1486      t2 += m2.no_rows;
1487    }
1488
1489    return r;
1490  }
1491
1492#if defined(HAVE_BLAS)
1493  template<> const vec operator*(const mat &m, const vec &v);
1494  template<> const cvec operator*(const cmat &m, const cvec &v);
1495#endif
1496
1497  template<class Num_T>
1498  const Vec<Num_T> operator*(const Mat<Num_T> &m, const Vec<Num_T> &v)
1499  {
1500    it_assert_debug(m.no_cols == v.size(),"Mat<Num_T>::operator*: wrong sizes");
1501    Vec<Num_T> r(m.no_rows);
1502    int i, k, m_pos;
1503
1504    for (i=0; i<m.no_rows; i++) {
1505      r(i) = Num_T(0);
1506      m_pos = 0;
1507      for (k=0; k<m.no_cols; k++) {
1508        r(i) += m.data[m_pos+i] * v(k);
1509        m_pos += m.no_rows;
1510      }
1511    }
1512
1513    return r;
1514  }
1515
1516  template<class Num_T> inline
1517  const Mat<Num_T> operator*(const Vec<Num_T> &v, const Mat<Num_T> &m)
1518  {
1519    it_assert((m.no_rows == 1),"Mat<Num_T>::operator*(): wrong sizes");
1520    it_warning("Mat<Num_T>::operator*(v, m): This operator is deprecated. "
1521               "Please use outer_product(v, m.get_row(0)) instead.");
1522    return outer_product(v, m.get_row(0));
1523  }
1524
1525  template<class Num_T> inline
1526  const Mat<Num_T> operator*(const Mat<Num_T> &m, Num_T t)
1527  {
1528    Mat<Num_T> r(m.no_rows, m.no_cols);
1529
1530    for (int i=0; i<r.datasize; i++)
1531      r.data[i] = m.data[i] * t;
1532
1533    return r;
1534  }
1535
1536  template<class Num_T> inline
1537  const Mat<Num_T> operator*(Num_T t, const Mat<Num_T> &m)
1538  {
1539    return operator*(m, t);
1540  }
1541
1542  template<class Num_T> inline
1543  const Mat<Num_T> elem_mult(const Mat<Num_T> &A, const Mat<Num_T> &B)
1544  {
1545    Mat<Num_T> out;
1546    elem_mult_out(A,B,out);
1547    return out;
1548  }
1549
1550  template<class Num_T> inline
1551  void elem_mult_out(const Mat<Num_T> &A, const Mat<Num_T> &B, Mat<Num_T> &out)
1552  {
1553    it_assert_debug( (A.no_rows==B.no_rows) && (A.no_cols==B.no_cols), "Mat<Num_T>::elem_mult_out: wrong sizes");
1554
1555    if( (out.no_rows != A.no_rows) || (out.no_cols != A.no_cols) )
1556      out.set_size(A.no_rows, A.no_cols);
1557
1558    for(int i=0; i<out.datasize; i++)
1559      out.data[i] = A.data[i] * B.data[i];
1560  }
1561
1562  template<class Num_T> inline
1563  void elem_mult_out(const Mat<Num_T> &A, const Mat<Num_T> &B, const Mat<Num_T> &C, Mat<Num_T> &out)
1564  {
1565    it_assert_debug( (A.no_rows==B.no_rows==C.no_rows) \
1566                && (A.no_cols==B.no_cols==C.no_cols), \
1567                "Mat<Num_T>::elem_mult_out: wrong sizes" );
1568
1569    if( (out.no_rows != A.no_rows) || (out.no_cols != A.no_cols) )
1570      out.set_size(A.no_rows, A.no_cols);
1571
1572    for(int i=0; i<out.datasize; i++)
1573      out.data[i] = A.data[i] * B.data[i] * C.data[i];
1574  }
1575
1576  template<class Num_T> inline
1577  void elem_mult_out(const Mat<Num_T> &A, const Mat<Num_T> &B, const Mat<Num_T> &C, const Mat<Num_T> &D, Mat<Num_T> &out)
1578  {
1579    it_assert_debug( (A.no_rows==B.no_rows==C.no_rows==D.no_rows) \
1580                && (A.no_cols==B.no_cols==C.no_cols==D.no_cols), \
1581                "Mat<Num_T>::elem_mult_out: wrong sizes" );
1582    if( (out.no_rows != A.no_rows) || (out.no_cols != A.no_cols) )
1583      out.set_size(A.no_rows, A.no_cols);
1584
1585    for(int i=0; i<out.datasize; i++)
1586      out.data[i] = A.data[i] * B.data[i] * C.data[i] * D.data[i];
1587  }
1588
1589  template<class Num_T> inline
1590  void elem_mult_inplace(const Mat<Num_T> &A, Mat<Num_T> &B)
1591  {
1592    it_assert_debug( (A.no_rows==B.no_rows) && (A.no_cols==B.no_cols), \
1593                "Mat<Num_T>::elem_mult_inplace: wrong sizes" );
1594
1595    for(int i=0; i<B.datasize; i++)
1596      B.data[i] *= A.data[i];
1597  }
1598
1599  template<class Num_T> inline
1600  Num_T elem_mult_sum(const Mat<Num_T> &A, const Mat<Num_T> &B)
1601  {
1602    it_assert_debug( (A.no_rows==B.no_rows) && (A.no_cols==B.no_cols), "Mat<Num_T>::elem_mult_sum: wrong sizes" );
1603
1604    Num_T acc = 0;
1605
1606    for(int i=0; i<A.datasize; i++)
1607      acc += A.data[i] * B.data[i];
1608
1609    return acc;
1610  }
1611
1612  template<class Num_T> inline
1613  Mat<Num_T>& Mat<Num_T>::operator/=(Num_T t)
1614  {
1615    for (int i=0; i<datasize; i++)
1616      data[i] /= t;
1617    return *this;
1618  }
1619
1620  template<class Num_T> inline
1621  const Mat<Num_T> operator/(const Mat<Num_T> &m, Num_T t)
1622  {
1623    Mat<Num_T> r(m.no_rows, m.no_cols);
1624
1625    for (int i=0; i<r.datasize; i++)
1626      r.data[i] = m.data[i] / t;
1627
1628    return r;
1629  }
1630
1631  template<class Num_T> inline
1632  Mat<Num_T>& Mat<Num_T>::operator/=(const Mat<Num_T> &m)
1633  {
1634    it_assert_debug(m.no_rows==no_rows && m.no_cols==no_cols, "Mat<Num_T>::operator/=: wrong sizes");
1635
1636    for (int i=0; i<datasize; i++)
1637      data[i] /= m.data[i];
1638    return *this;
1639  }
1640
1641  template<class Num_T> inline
1642  const Mat<Num_T> elem_div(const Mat<Num_T> &A, const Mat<Num_T> &B)
1643  {
1644    Mat<Num_T> out;
1645    elem_div_out(A,B,out);
1646    return out;
1647  }
1648
1649  template<class Num_T> inline
1650  void elem_div_out(const Mat<Num_T> &A, const Mat<Num_T> &B, Mat<Num_T> &out)
1651  {
1652    it_assert_debug( (A.no_rows==B.no_rows) && (A.no_cols==B.no_cols), "Mat<Num_T>::elem_div_out: wrong sizes");
1653
1654    if( (out.no_rows != A.no_rows) || (out.no_cols != A.no_cols) )
1655      out.set_size(A.no_rows, A.no_cols);
1656
1657    for(int i=0; i<out.datasize; i++)
1658      out.data[i] = A.data[i] / B.data[i];
1659  }
1660
1661  template<class Num_T> inline
1662  Num_T elem_div_sum(const Mat<Num_T> &A, const Mat<Num_T> &B)
1663  {
1664    it_assert_debug( (A.no_rows==B.no_rows) && (A.no_cols==B.no_cols), "Mat<Num_T>::elem_div_sum: wrong sizes" );
1665
1666    Num_T acc = 0;
1667
1668    for(int i=0; i<A.datasize; i++)
1669      acc += A.data[i] / B.data[i];
1670
1671    return acc;
1672  }
1673
1674  template<class Num_T>
1675  bool Mat<Num_T>::operator==(const Mat<Num_T> &m) const
1676  {
1677    if (no_rows!=m.no_rows || no_cols != m.no_cols) return false;
1678    for (int i=0;i<datasize;i++) {
1679      if (data[i]!=m.data[i]) return false;
1680    }
1681    return true;
1682  }
1683
1684  template<class Num_T>
1685  bool Mat<Num_T>::operator!=(const Mat<Num_T> &m) const
1686  {
1687    if (no_rows != m.no_rows || no_cols != m.no_cols) return true;
1688    for (int i=0;i<datasize;i++) {
1689      if (data[i]!=m.data[i]) return true;
1690    }
1691    return false;
1692  }
1693
1694  template <class Num_T>
1695  std::ostream &operator<<(std::ostream &os, const Mat<Num_T> &m)
1696  {
1697    int i;
1698
1699    switch (m.rows()) {
1700    case 0 :
1701      os << "[]";
1702      break;
1703    case 1 :
1704      os << '[' << m.get_row(0) << ']';
1705      break;
1706    default:
1707      os << '[' << m.get_row(0) << std::endl;
1708      for (i=1; i<m.rows()-1; i++)
1709              os << ' ' << m.get_row(i) << std::endl;
1710      os << ' ' << m.get_row(m.rows()-1) << ']';
1711    }
1712
1713    return os;
1714  }
1715
1716  template <class Num_T>
1717  std::istream &operator>>(std::istream &is, Mat<Num_T> &m)
1718  {
1719    std::ostringstream buffer;
1720    bool started = false;
1721    bool finished = false;
1722    bool brackets = false;
1723    bool within_double_brackets = false;
1724    char c;
1725
1726    while (!finished) {
1727      if (is.eof()) {
1728        finished = true;
1729      } else {
1730        c = is.get();
1731
1732        if (is.eof() || (c == '\n')) {
1733          if (brackets) {
1734            // Right bracket missing
1735            is.setstate(std::ios_base::failbit);
1736            finished = true;
1737          } else if (!((c == '\n') && !started)) {
1738            finished = true;
1739          }
1740        } else if ((c == ' ') || (c == '\t')) {
1741          if (started) {
1742            buffer << ' ';
1743          }
1744        } else if (c == '[') {
1745          if ((started && !brackets) || within_double_brackets) {
1746            // Unexpected left bracket
1747            is.setstate(std::ios_base::failbit);
1748            finished = true;
1749          } else if (!started) {
1750            started = true;
1751            brackets = true;
1752          } else {
1753            within_double_brackets = true;
1754          }
1755        } else if (c == ']') {
1756          if (!started || !brackets) {
1757            // Unexpected right bracket
1758            is.setstate(std::ios_base::failbit);
1759            finished = true;
1760          } else if (within_double_brackets) {
1761            within_double_brackets = false;
1762            buffer << ';';
1763          } else {
1764            finished = true;
1765          }
1766          while (!is.eof() && (((c = is.peek()) == ' ') || (c == '\t'))) {
1767            is.get();
1768          }
1769          if (!is.eof() && (c == '\n')) {
1770            is.get();
1771          }
1772        } else {
1773          started = true;
1774          buffer << c;
1775        }
1776      }
1777    }
1778
1779    if (!started) {
1780      m.set_size(0, false);
1781    } else {
1782      m.set(buffer.str());
1783    }
1784
1785    return is;
1786  }
1787
1788  //! \cond
1789
1790  // ---------------------------------------------------------------------
1791  // Instantiations
1792  // ---------------------------------------------------------------------
1793
1794#ifdef HAVE_EXTERN_TEMPLATE
1795
1796  // class instantiations
1797
1798  extern template class Mat<double>;
1799  extern template class Mat<std::complex<double> >;
1800  extern template class Mat<int>;
1801  extern template class Mat<short int>;
1802  extern template class Mat<bin>;
1803
1804  // addition operators
1805
1806  extern template const mat operator+(const mat &m1, const mat &m2);
1807  extern template const cmat operator+(const cmat &m1, const cmat &m2);
1808  extern template const imat operator+(const imat &m1, const imat &m2);
1809  extern template const smat operator+(const smat &m1, const smat &m2);
1810  extern template const bmat operator+(const bmat &m1, const bmat &m2);
1811
1812  extern template const mat operator+(const mat &m, double t);
1813  extern template const cmat operator+(const cmat &m, std::complex<double> t);
1814  extern template const imat operator+(const imat &m, int t);
1815  extern template const smat operator+(const smat &m, short t);
1816  extern template const bmat operator+(const bmat &m, bin t);
1817
1818  extern template const mat operator+(double t, const mat &m);
1819  extern template const cmat operator+(std::complex<double> t, const cmat &m);
1820  extern template const imat operator+(int t, const imat &m);
1821  extern template const smat operator+(short t, const smat &m);
1822  extern template const bmat operator+(bin t, const bmat &m);
1823
1824  // subraction operators
1825
1826  extern template const mat operator-(const mat &m1, const mat &m2);
1827  extern template const cmat operator-(const cmat &m1, const cmat &m2);
1828  extern template const imat operator-(const imat &m1, const imat &m2);
1829  extern template const smat operator-(const smat &m1, const smat &m2);
1830  extern template const bmat operator-(const bmat &m1, const bmat &m2);
1831
1832  extern template const mat operator-(const mat &m, double t);
1833  extern template const cmat operator-(const cmat &m, std::complex<double> t);
1834  extern template const imat operator-(const imat &m, int t);
1835  extern template const smat operator-(const smat &m, short t);
1836  extern template const bmat operator-(const bmat &m, bin t);
1837
1838  extern template const mat operator-(double t, const mat &m);
1839  extern template const cmat operator-(std::complex<double> t, const cmat &m);
1840  extern template const imat operator-(int t, const imat &m);
1841  extern template const smat operator-(short t, const smat &m);
1842  extern template const bmat operator-(bin t, const bmat &m);
1843
1844  // unary minus
1845
1846  extern template const mat operator-(const mat &m);
1847  extern template const cmat operator-(const cmat &m);
1848  extern template const imat operator-(const imat &m);
1849  extern template const smat operator-(const smat &m);
1850  extern template const bmat operator-(const bmat &m);
1851
1852  // multiplication operators
1853
1854#if !defined(HAVE_BLAS)
1855  extern template const mat operator*(const mat &m1, const mat &m2);
1856  extern template const cmat operator*(const cmat &m1, const cmat &m2);
1857#endif
1858  extern template const imat operator*(const imat &m1, const imat &m2);
1859  extern template const smat operator*(const smat &m1, const smat &m2);
1860  extern template const bmat operator*(const bmat &m1, const bmat &m2);
1861
1862#if !defined(HAVE_BLAS)
1863  extern template const vec operator*(const mat &m, const vec &v);
1864  extern template const cvec operator*(const cmat &m, const cvec &v);
1865#endif
1866  extern template const ivec operator*(const imat &m, const ivec &v);
1867  extern template const svec operator*(const smat &m, const svec &v);
1868  extern template const bvec operator*(const bmat &m, const bvec &v);
1869
1870  extern template const mat operator*(const vec &v, const mat &m);
1871  extern template const cmat operator*(const cvec &v, const cmat &m);
1872  extern template const imat operator*(const ivec &v, const imat &m);
1873  extern template const smat operator*(const svec &v, const smat &m);
1874  extern template const bmat operator*(const bvec &v, const bmat &m);
1875
1876  extern template const mat operator*(const mat &m, double t);
1877  extern template const cmat operator*(const cmat &m, std::complex<double> t);
1878  extern template const imat operator*(const imat &m, int t);
1879  extern template const smat operator*(const smat &m, short t);
1880  extern template const bmat operator*(const bmat &m, bin t);
1881
1882  extern template const mat operator*(double t, const mat &m);
1883  extern template const cmat operator*(std::complex<double> t, const cmat &m);
1884  extern template const imat operator*(int t, const imat &m);
1885  extern template const smat operator*(short t, const smat &m);
1886  extern template const bmat operator*(bin t, const bmat &m);
1887
1888  // elementwise multiplication
1889
1890  extern template const mat elem_mult(const mat &A, const mat &B);
1891  extern template const cmat elem_mult(const cmat &A, const cmat &B);
1892  extern template const imat elem_mult(const imat &A, const imat &B);
1893  extern template const smat elem_mult(const smat &A, const smat &B);
1894  extern template const bmat elem_mult(const bmat &A, const bmat &B);
1895
1896  extern template void elem_mult_out(const mat &A, const mat &B, mat &out);
1897  extern template void elem_mult_out(const cmat &A, const cmat &B, cmat &out);
1898  extern template void elem_mult_out(const imat &A, const imat &B, imat &out);
1899  extern template void elem_mult_out(const smat &A, const smat &B, smat &out);
1900  extern template void elem_mult_out(const bmat &A, const bmat &B, bmat &out);
1901
1902  extern template void elem_mult_out(const mat &A, const mat &B, const mat &C,
1903                                     mat &out);
1904  extern template void elem_mult_out(const cmat &A, const cmat &B,
1905                                     const cmat &C, cmat &out);
1906  extern template void elem_mult_out(const imat &A, const imat &B,
1907                                     const imat &C, imat &out);
1908  extern template void elem_mult_out(const smat &A, const smat &B,
1909                                     const smat &C, smat &out);
1910  extern template void elem_mult_out(const bmat &A, const bmat &B,
1911                                     const bmat &C, bmat &out);
1912
1913  extern template void elem_mult_out(const mat &A, const mat &B, const mat &C,
1914                                     const mat &D, mat &out);
1915  extern template void elem_mult_out(const cmat &A, const cmat &B,
1916                                     const cmat &C, const cmat &D, cmat &out);
1917  extern template void elem_mult_out(const imat &A, const imat &B,
1918                                     const imat &C, const imat &D, imat &out);
1919  extern template void elem_mult_out(const smat &A, const smat &B,
1920                                     const smat &C, const smat &D, smat &out);
1921  extern template void elem_mult_out(const bmat &A, const bmat &B,
1922                                     const bmat &C, const bmat &D, bmat &out);
1923
1924  extern template void elem_mult_inplace(const mat &A, mat &B);
1925  extern template void elem_mult_inplace(const cmat &A, cmat &B);
1926  extern template void elem_mult_inplace(const imat &A, imat &B);
1927  extern template void elem_mult_inplace(const smat &A, smat &B);
1928  extern template void elem_mult_inplace(const bmat &A, bmat &B);
1929
1930  extern template double elem_mult_sum(const mat &A, const mat &B);
1931  extern template std::complex<double> elem_mult_sum(const cmat &A,
1932                                                     const cmat &B);
1933  extern template int elem_mult_sum(const imat &A, const imat &B);
1934  extern template short elem_mult_sum(const smat &A, const smat &B);
1935  extern template bin elem_mult_sum(const bmat &A, const bmat &B);
1936
1937  // division operator
1938
1939  extern template const mat operator/(const mat &m, double t);
1940  extern template const cmat operator/(const cmat &m, std::complex<double> t);
1941  extern template const imat operator/(const imat &m, int t);
1942  extern template const smat operator/(const smat &m, short t);
1943  extern template const bmat operator/(const bmat &m, bin t);
1944
1945  // elementwise division
1946
1947  extern template const mat elem_div(const mat &A, const mat &B);
1948  extern template const cmat elem_div(const cmat &A, const cmat &B);
1949  extern template const imat elem_div(const imat &A, const imat &B);
1950  extern template const smat elem_div(const smat &A, const smat &B);
1951  extern template const bmat elem_div(const bmat &A, const bmat &B);
1952
1953  extern template void elem_div_out(const mat &A, const mat &B, mat &out);
1954  extern template void elem_div_out(const cmat &A, const cmat &B, cmat &out);
1955  extern template void elem_div_out(const imat &A, const imat &B, imat &out);
1956  extern template void elem_div_out(const smat &A, const smat &B, smat &out);
1957  extern template void elem_div_out(const bmat &A, const bmat &B, bmat &out);
1958
1959  extern template double elem_div_sum(const mat &A, const mat &B);
1960  extern template std::complex<double> elem_div_sum(const cmat &A,
1961                                                    const cmat &B);
1962  extern template int elem_div_sum(const imat &A, const imat &B);
1963  extern template short elem_div_sum(const smat &A, const smat &B);
1964  extern template bin elem_div_sum(const bmat &A, const bmat &B);
1965
1966  // concatenation
1967
1968  extern template const mat concat_horizontal(const mat &m1, const mat &m2);
1969  extern template const cmat concat_horizontal(const cmat &m1, const cmat &m2);
1970  extern template const imat concat_horizontal(const imat &m1, const imat &m2);
1971  extern template const smat concat_horizontal(const smat &m1, const smat &m2);
1972  extern template const bmat concat_horizontal(const bmat &m1, const bmat &m2);
1973
1974  extern template const mat concat_vertical(const mat &m1, const mat &m2);
1975  extern template const cmat concat_vertical(const cmat &m1, const cmat &m2);
1976  extern template const imat concat_vertical(const imat &m1, const imat &m2);
1977  extern template const smat concat_vertical(const smat &m1, const smat &m2);
1978  extern template const bmat concat_vertical(const bmat &m1, const bmat &m2);
1979
1980  // I/O streams
1981
1982  extern template std::ostream &operator<<(std::ostream &os, const mat  &m);
1983  extern template std::ostream &operator<<(std::ostream &os, const cmat &m);
1984  extern template std::ostream &operator<<(std::ostream &os, const imat  &m);
1985  extern template std::ostream &operator<<(std::ostream &os, const smat  &m);
1986  extern template std::ostream &operator<<(std::ostream &os, const bmat  &m);
1987
1988  extern template std::istream &operator>>(std::istream &is, mat  &m);
1989  extern template std::istream &operator>>(std::istream &is, cmat &m);
1990  extern template std::istream &operator>>(std::istream &is, imat  &m);
1991  extern template std::istream &operator>>(std::istream &is, smat  &m);
1992  extern template std::istream &operator>>(std::istream &is, bmat  &m);
1993
1994#endif // HAVE_EXTERN_TEMPLATE
1995
1996  //! \endcond
1997
1998} // namespace itpp
1999
2000#endif // #ifndef MAT_H
Note: See TracBrowser for help on using the browser.