1 /*
2   Copyright 2009 Andreas Biegert
3 
4   This file is part of the CS-BLAST package.
5 
6   The CS-BLAST package is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10 
11   The CS-BLAST package is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef CS_MATRIX_H_
21 #define CS_MATRIX_H_
22 
23 #include <numeric>
24 #include <algorithm>
25 #include <iomanip>
26 
27 
28 template <class T>
29 class Matrix {
30  public:
31   typedef T value_type;
32 
33   Matrix();
34   Matrix(size_t n, size_t m);
35   Matrix(size_t n, size_t m, const T &a);
36   Matrix(size_t n, size_t m, const T *a);
37   Matrix(const Matrix &rhs);
38   ~Matrix();
39 
40   Matrix & operator=(const Matrix &rhs);
41   T* operator[](const size_t i);
42   const T* operator[](const size_t i) const;
43   size_t nrows() const;
44   size_t ncols() const;
45   void Resize(size_t newn, size_t newm);
46   void Assign(size_t newn, size_t newm, const T &a);
begin()47   T* begin() { return *v; }
begin()48   const T* begin() const { return *v; }
49 
50  private:
51   size_t nn;
52   size_t mm;
53   T **v;
54 };
55 
56 template <class T>
Matrix()57 Matrix<T>::Matrix() : nn(0), mm(0), v(NULL) {}
58 
59 template <class T>
Matrix(size_t n,size_t m)60 Matrix<T>::Matrix(size_t n, size_t m) : nn(n), mm(m), v(n>0 ? new T*[n] : NULL) {
61   size_t i,nel=m*n;
62   if (v) v[0] = nel>0 ? new T[nel] : NULL;
63   for (i=1;i<n;i++) v[i] = v[i-1] + m;
64 }
65 
66 template <class T>
Matrix(size_t n,size_t m,const T & a)67 Matrix<T>::Matrix(size_t n, size_t m, const T &a) : nn(n), mm(m), v(n>0 ? new T*[n] : NULL) {
68   size_t i,j,nel=m*n;
69   if (v) v[0] = nel>0 ? new T[nel] : NULL;
70   for (i=1; i< n; i++) v[i] = v[i-1] + m;
71   for (i=0; i< n; i++) for (j=0; j<m; j++) v[i][j] = a;
72 }
73 
74 template <class T>
Matrix(size_t n,size_t m,const T * a)75 Matrix<T>::Matrix(size_t n, size_t m, const T *a) : nn(n), mm(m), v(n>0 ? new T*[n] : NULL) {
76   size_t i,j,nel=m*n;
77   if (v) v[0] = nel>0 ? new T[nel] : NULL;
78   for (i=1; i< n; i++) v[i] = v[i-1] + m;
79   for (i=0; i< n; i++) for (j=0; j<m; j++) v[i][j] = *a++;
80 }
81 
82 template <class T>
Matrix(const Matrix & rhs)83 Matrix<T>::Matrix(const Matrix &rhs) : nn(rhs.nn), mm(rhs.mm), v(nn>0 ? new T*[nn] : NULL) {
84   size_t i,j,nel=mm*nn;
85   if (v) v[0] = nel>0 ? new T[nel] : NULL;
86   for (i=1; i< nn; i++) v[i] = v[i-1] + mm;
87   for (i=0; i< nn; i++) for (j=0; j<mm; j++) v[i][j] = rhs[i][j];
88 }
89 
90 template <class T>
91 Matrix<T> & Matrix<T>::operator=(const Matrix<T> &rhs) {
92   if (this != &rhs) {
93     size_t i,j,nel;
94     if (nn != rhs.nn || mm != rhs.mm) {
95       if (v != NULL) {
96         delete[] (v[0]);
97         delete[] (v);
98       }
99       nn=rhs.nn;
100       mm=rhs.mm;
101       v = nn>0 ? new T*[nn] : NULL;
102       nel = mm*nn;
103       if (v) v[0] = nel>0 ? new T[nel] : NULL;
104       for (i=1; i< nn; i++) v[i] = v[i-1] + mm;
105     }
106     for (i=0; i< nn; i++) for (j=0; j<mm; j++) v[i][j] = rhs[i][j];
107   }
108   return *this;
109 }
110 
111 template <class T>
112 inline T* Matrix<T>::operator[](const size_t i) {
113 #ifdef CHECKBOUNDS
114   if (i<0 || i>=nn) {
115     throw Exception("Matrix subscript out of bounds");
116   }
117 #endif
118   return v[i];
119 }
120 
121 template <class T>
122 inline const T* Matrix<T>::operator[](const size_t i) const {
123 #ifdef CHECKBOUNDS
124   if (i<0 || i>=nn) {
125     throw Excpetion("Matrix subscript out of bounds");
126   }
127 #endif
128   return v[i];
129 }
130 
131 template <class T>
nrows()132 inline size_t Matrix<T>::nrows() const {
133   return nn;
134 }
135 
136 template <class T>
ncols()137 inline size_t Matrix<T>::ncols() const {
138   return mm;
139 }
140 
141 template <class T>
Resize(size_t newn,size_t newm)142 void Matrix<T>::Resize(size_t newn, size_t newm) {
143   size_t i,nel;
144   if (newn != nn || newm != mm) {
145     if (v != NULL) {
146       delete[] (v[0]);
147       delete[] (v);
148     }
149     nn = newn;
150     mm = newm;
151     v = nn>0 ? new T*[nn] : NULL;
152     nel = mm*nn;
153     if (v) v[0] = nel>0 ? new T[nel] : NULL;
154     for (i=1; i< nn; i++) v[i] = v[i-1] + mm;
155   }
156 }
157 
158 template <class T>
Assign(size_t newn,size_t newm,const T & a)159 void Matrix<T>::Assign(size_t newn, size_t newm, const T& a) {
160   size_t i,j,nel;
161   if (newn != nn || newm != mm) {
162     if (v != NULL) {
163       delete[] (v[0]);
164       delete[] (v);
165     }
166     nn = newn;
167     mm = newm;
168     v = nn>0 ? new T*[nn] : NULL;
169     nel = mm*nn;
170     if (v) v[0] = nel>0 ? new T[nel] : NULL;
171     for (i=1; i< nn; i++) v[i] = v[i-1] + mm;
172   }
173   for (i=0; i< nn; i++) for (j=0; j<mm; j++) v[i][j] = a;
174 }
175 
176 template <class T>
~Matrix()177 Matrix<T>::~Matrix() {
178   if (v != NULL) {
179     delete[] (v[0]);
180     delete[] (v);
181   }
182 }
183 
184 // Assigns given constant value or default to all entries in matrix
185 template<class T>
186 inline void Assign(Matrix<T>& m, T val = T()) {
187   for (size_t i = 0; i < m.nrows(); ++i)
188     for (size_t j = 0; j < m.ncols(); ++j)
189       m[i][j] = val;
190 }
191 
192 // Prints profile in human-readable format for debugging.
193 template<class T>
194 std::ostream& operator<< (std::ostream& out, const Matrix<T>& m) {
195     out << "Matrix" << std::endl;
196     for (size_t j = 0; j < m.ncols(); ++j)
197         out << "\t" << j;
198     out << std::endl;
199     for (size_t i = 0; i < m.nrows(); ++i) {
200         out << i;
201         for (size_t j = 0; j < m.ncols(); ++j)
202             out << "\t" << std::setprecision(4) << m[i][j];
203         out << std::endl;
204     }
205     return out;
206 }
207 
208 #endif  // CS_MATRIX_H_
209