RDKit
Open-source cheminformatics and machine learning.
Matrix.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2004-2006 Rational Discovery LLC
3 //
4 // @@ All Rights Reserved @@
5 // This file is part of the RDKit.
6 // The contents are covered by the terms of the BSD license
7 // which is included in the file license.txt, found at the root
8 // of the RDKit source tree.
9 //
10 #ifndef __RD_MATRIX_H__
11 #define __RD_MATRIX_H__
12 
13 #include <RDGeneral/Invariant.h>
14 #include "Vector.h"
15 #include <iostream>
16 #include <iomanip>
17 #include <cstring>
18 #include <boost/smart_ptr.hpp>
19 
20 //#ifndef INVARIANT_SILENT_METHOD
21 //#define INVARIANT_SILENT_METHOD
22 //#endif
23 
24 namespace RDNumeric {
25 
26  //! A matrix class for general, non-square matrices
27  template <class TYPE> class Matrix {
28  public:
29 
30  typedef boost::shared_array<TYPE> DATA_SPTR;
31 
32  //! Initialize with a size.
33  Matrix(unsigned int nRows, unsigned int nCols) :
34  d_nRows(nRows), d_nCols(nCols), d_dataSize(nRows*nCols) {
35  TYPE *data = new TYPE[d_dataSize];
36  memset(static_cast<void *>(data),0,d_dataSize*sizeof(TYPE));
37  d_data.reset(data);
38  };
39 
40  //! Initialize with a size and default value.
41  Matrix(unsigned int nRows, unsigned int nCols, TYPE val) :
42  d_nRows(nRows), d_nCols(nCols), d_dataSize(nRows*nCols) {
43  TYPE *data = new TYPE[d_dataSize];
44  unsigned int i;
45  for (i = 0; i < d_dataSize; i++) {
46  data[i] = val;
47  }
48  d_data.reset(data);
49  }
50 
51  //! Initialize from a pointer.
52  /*!
53  <b>NOTE:</b> this does not take ownership of the data,
54  if you delete the data externally, this Matrix will be sad.
55  */
56  Matrix(unsigned int nRows, unsigned int nCols, DATA_SPTR data) :
57  d_nRows(nRows), d_nCols(nCols), d_dataSize(nRows*nCols) {
58  d_data = data;
59  }
60 
61  //! copy constructor
62  /*! We make a copy of the other vector's data.
63  */
64  Matrix(const Matrix<TYPE> &other) :
65  d_nRows(other.numRows()), d_nCols(other.numCols()), d_dataSize(d_nRows*d_nCols) {
66  TYPE *data = new TYPE[d_dataSize];
67  const TYPE *otherData = other.getData();
68  memcpy(static_cast<void *>(data), static_cast<const void *>(otherData),
69  d_dataSize*sizeof(TYPE));
70  d_data.reset(data);
71  }
72 
73  virtual ~Matrix() {
74  }
75 
76  //! returns the number of rows
77  inline unsigned int numRows() const {
78  return d_nRows;
79  }
80 
81  //! returns the number of columns
82  inline unsigned int numCols() const {
83  return d_nCols;
84  }
85 
86  inline unsigned int getDataSize() const {
87  return d_dataSize;
88  }
89 
90  //! returns a particular element of the matrix
91  inline virtual TYPE getVal(unsigned int i, unsigned int j) const {
92  PRECONDITION(i<d_nRows,"bad index");
93  PRECONDITION(j<d_nCols,"bad index");
94  unsigned int id = i*d_nCols + j;
95  return d_data[id];
96  }
97 
98  //! sets a particular element of the matrix
99  inline virtual void setVal(unsigned int i, unsigned int j, TYPE val) {
100  PRECONDITION(i<d_nRows,"bad index");
101  PRECONDITION(j<d_nCols,"bad index");
102  unsigned int id = i*d_nCols + j;
103 
104  d_data[id] = val;
105  }
106 
107  //! returns a copy of a row of the matrix
108  inline virtual void getRow(unsigned int i, Vector<TYPE> &row) const {
109  PRECONDITION(i<d_nRows,"bad index");
110  PRECONDITION(d_nCols == row.size(), "");
111  unsigned int id = i*d_nCols;
112  TYPE *rData = row.getData();
113  TYPE *data = d_data.get();
114  memcpy(static_cast<void *>(rData), static_cast<void *>(&data[id]), d_nCols*sizeof(TYPE));
115 
116  }
117 
118  //! returns a copy of a column of the matrix
119  inline virtual void getCol(unsigned int i, Vector<TYPE> &col) const {
120  PRECONDITION(i<d_nCols,"bad index");
121  PRECONDITION(d_nRows == col.size(), "");
122  unsigned int j,id;
123  TYPE *rData = col.getData();
124  TYPE *data = d_data.get();
125  for (j = 0; j < d_nRows; j++) {
126  id = j*d_nCols + i;
127  rData[j] = data[id];
128  }
129  }
130 
131  //! returns a pointer to our data array
132  inline TYPE *getData() {
133  return d_data.get();
134  }
135 
136  //! returns a const pointer to our data array
137  inline const TYPE *getData() const {
138  return d_data.get();
139  }
140 
141 
142  //! Copy operator.
143  /*! We make a copy of the other Matrix's data.
144  */
145 
147  PRECONDITION(d_nRows == other.numRows(), "Num rows mismatch in matrix copying");
148  PRECONDITION(d_nCols == other.numCols(), "Num cols mismatch in matrix copying");
149  const TYPE *otherData = other.getData();
150  TYPE *data = d_data.get();
151  memcpy(static_cast<void *>(data), static_cast<const void *>(otherData), d_dataSize*sizeof(TYPE));
152  return *this;
153  }
154 
155  //! Matrix addition.
156  /*! Perform a element by element addition of other Matrix to this Matrix
157  */
158  virtual Matrix<TYPE>& operator+=(const Matrix<TYPE> &other) {
159  PRECONDITION(d_nRows == other.numRows(), "Num rows mismatch in matrix addition");
160  PRECONDITION(d_nCols == other.numCols(), "Num cols mismatch in matrix addition");
161  const TYPE *oData = other.getData();
162  unsigned int i;
163  TYPE *data = d_data.get();
164  for (i = 0; i < d_dataSize; i++) {
165  data[i] += oData[i];
166  }
167  return *this;
168  }
169 
170  //! Matrix subtraction.
171  /*! Perform a element by element subtraction of other Matrix from this Matrix
172  */
173  virtual Matrix<TYPE>& operator-=(const Matrix<TYPE> &other) {
174  PRECONDITION(d_nRows == other.numRows(), "Num rows mismatch in matrix addition");
175  PRECONDITION(d_nCols == other.numCols(), "Num cols mismatch in matrix addition");
176  const TYPE *oData = other.getData();
177  unsigned int i;
178  TYPE *data = d_data.get();
179  for (i = 0; i < d_dataSize; i++) {
180  data[i] -= oData[i];
181  }
182  return *this;
183  }
184 
185  //! Multiplication by a scalar
186  virtual Matrix<TYPE>& operator*=(TYPE scale) {
187  unsigned int i;
188  TYPE *data = d_data.get();
189  for (i = 0; i < d_dataSize; i++) {
190  data[i] *= scale;
191  }
192  return *this;
193  }
194 
195  //! division by a scalar
196  virtual Matrix<TYPE>& operator/=(TYPE scale) {
197  unsigned int i;
198  TYPE *data = d_data.get();
199  for (i = 0; i < d_dataSize; i++) {
200  data[i] /= scale;
201  }
202  return *this;
203  }
204 
205  //! copies the transpose of this Matrix into another, returns the result
206  /*!
207  \param transpose the Matrix to store the results
208 
209  \return the transpose of this matrix.
210  This is just a reference to the argument.
211 
212  */
214  unsigned int tRows = transpose.numRows();
215  unsigned int tCols = transpose.numCols();
216  PRECONDITION(d_nCols == tRows, "Size mismatch during transposing");
217  PRECONDITION(d_nRows == tCols, "Size mismatch during transposing");
218  unsigned int i, j;
219  unsigned int idA, idAt, idT;
220  TYPE *tData = transpose.getData();
221  TYPE *data = d_data.get();
222  for (i = 0; i < d_nRows; i++) {
223  idA = i*d_nCols;
224  for (j = 0; j < d_nCols; j++) {
225  idAt = idA + j;
226  idT = j*tCols + i;
227  tData[idT] = data[idAt];
228  }
229  }
230  return transpose;
231  }
232 
233  protected:
234  Matrix() : d_nRows(0), d_nCols(0), d_dataSize(0), d_data(){} ;
235  unsigned int d_nRows;
236  unsigned int d_nCols;
237  unsigned int d_dataSize;
238  DATA_SPTR d_data;
239 
240  private:
241  Matrix<TYPE>& operator=(const Matrix<TYPE> &other);
242  };
243 
244  //! Matrix multiplication
245  /*!
246  Multiply a Matrix A with a second Matrix B
247  so the result is C = A*B
248 
249  \param A the the first Matrix used in the multiplication
250  \param B the Matrix by which to multiply
251  \param C Matrix to use for the results
252 
253  \return the results of multiplying A by B.
254  This is just a reference to C.
255  */
256  template <class TYPE>
258  Matrix<TYPE> &C) {
259  unsigned int aRows = A.numRows();
260  unsigned int aCols = A.numCols();
261  unsigned int cRows = C.numRows();
262  unsigned int cCols = C.numCols();
263  unsigned int bRows = B.numRows();
264  unsigned int bCols = B.numCols();
265  CHECK_INVARIANT(aCols == bRows, "Size mismatch during multiplication");
266  CHECK_INVARIANT(aRows == cRows, "Size mismatch during multiplication");
267  CHECK_INVARIANT(bCols == cCols, "Size mismatch during multiplication");
268 
269  // we have the sizes check do do the multiplication
270  TYPE *cData = C.getData();
271  const TYPE *bData = B.getData();
272  const TYPE *aData = A.getData();
273  unsigned int i, j, k;
274  unsigned int idA, idAt, idB, idC, idCt;
275  for (i = 0; i < aRows; i++) {
276  idC = i*cCols;
277  idA = i*aCols;
278  for (j = 0; j < cCols; j++) {
279  idCt = idC + j;
280  cData[idCt] = (TYPE)0.0;
281  for (k = 0; k < aCols; k++) {
282  idAt = idA + k;
283  idB = k*bCols + j;
284  cData[idCt] += (aData[idAt]*bData[idB]);
285  }
286  }
287  }
288  return C;
289  };
290 
291  //! Matrix-Vector multiplication
292  /*!
293  Multiply a Matrix A with a Vector x
294  so the result is y = A*x
295 
296  \param A the matrix used in the multiplication
297  \param x the Vector by which to multiply
298  \param y Vector to use for the results
299 
300  \return the results of multiplying x by this
301  This is just a reference to y.
302  */
303  template <class TYPE>
305  Vector<TYPE> &y) {
306  unsigned int aRows = A.numRows();
307  unsigned int aCols = A.numCols();
308  unsigned int xSiz = x.size();
309  unsigned int ySiz = y.size();
310  CHECK_INVARIANT(aCols == xSiz, "Size mismatch during multiplication");
311  CHECK_INVARIANT(aRows == ySiz, "Size mismatch during multiplication");
312  unsigned int i, j;
313  unsigned int idA, idAt;
314  const TYPE *xData = x.getData();
315  const TYPE *aData = A.getData();
316  TYPE *yData = y.getData();
317  for (i = 0; i < aRows; i++) {
318  idA = i*aCols;
319  yData[i] = (TYPE)(0.0);
320  for (j = 0; j < aCols; j++) {
321  idAt = idA + j;
322  yData[i] += (aData[idAt]*xData[j]);
323  }
324  }
325  return y;
326  };
327 
329 };
330 
331 //! ostream operator for Matrix's
332 template <class TYPE > std::ostream & operator<<(std::ostream& target,
333  const RDNumeric::Matrix<TYPE> &mat) {
334  unsigned int nr = mat.numRows();
335  unsigned int nc = mat.numCols();
336  target << "Rows: " << mat.numRows() << " Columns: " << mat.numCols() << "\n";
337 
338  unsigned int i, j;
339  for (i = 0; i < nr; i++) {
340  for (j = 0; j < nc; j++) {
341  target << std::setw(7) << std::setprecision(3) << mat.getVal(i, j);
342  }
343  target << "\n";
344  }
345  return target;
346 }
347 
348 #endif
Matrix(unsigned int nRows, unsigned int nCols)
Initialize with a size.
Definition: Matrix.h:33
DATA_SPTR d_data
Definition: Matrix.h:238
virtual Matrix< TYPE > & operator-=(const Matrix< TYPE > &other)
Matrix subtraction.
Definition: Matrix.h:173
unsigned int numRows() const
returns the number of rows
Definition: Matrix.h:77
std::ostream & operator<<(std::ostream &target, const RDNumeric::Matrix< TYPE > &mat)
ostream operator for Matrix&#39;s
Definition: Matrix.h:332
#define CHECK_INVARIANT(expr, mess)
Definition: Invariant.h:114
virtual Matrix< TYPE > & operator*=(TYPE scale)
Multiplication by a scalar.
Definition: Matrix.h:186
virtual void setVal(unsigned int i, unsigned int j, TYPE val)
sets a particular element of the matrix
Definition: Matrix.h:99
Matrix(unsigned int nRows, unsigned int nCols, TYPE val)
Initialize with a size and default value.
Definition: Matrix.h:41
Matrix< TYPE > & assign(const Matrix< TYPE > &other)
Copy operator.
Definition: Matrix.h:146
virtual Matrix< TYPE > & transpose(Matrix< TYPE > &transpose) const
copies the transpose of this Matrix into another, returns the result
Definition: Matrix.h:213
unsigned int size() const
return the size (dimension) of the vector
Definition: Vector.h:79
virtual ~Matrix()
Definition: Matrix.h:73
unsigned int d_nCols
Definition: Matrix.h:236
Matrix(unsigned int nRows, unsigned int nCols, DATA_SPTR data)
Initialize from a pointer.
Definition: Matrix.h:56
A matrix class for general, non-square matrices.
Definition: Matrix.h:27
boost::shared_array< TYPE > DATA_SPTR
Definition: Matrix.h:30
const TYPE * getData() const
returns a const pointer to our data array
Definition: Matrix.h:137
unsigned int numCols() const
returns the number of columns
Definition: Matrix.h:82
Matrix< double > DoubleMatrix
Definition: Matrix.h:326
Matrix< TYPE > & multiply(const Matrix< TYPE > &A, const Matrix< TYPE > &B, Matrix< TYPE > &C)
Matrix multiplication.
Definition: Matrix.h:257
unsigned int d_nRows
Definition: Matrix.h:234
virtual TYPE getVal(unsigned int i, unsigned int j) const
returns a particular element of the matrix
Definition: Matrix.h:91
virtual Matrix< TYPE > & operator+=(const Matrix< TYPE > &other)
Matrix addition.
Definition: Matrix.h:158
virtual Matrix< TYPE > & operator/=(TYPE scale)
division by a scalar
Definition: Matrix.h:196
#define PRECONDITION(expr, mess)
Definition: Invariant.h:119
virtual void getCol(unsigned int i, Vector< TYPE > &col) const
returns a copy of a column of the matrix
Definition: Matrix.h:119
virtual void getRow(unsigned int i, Vector< TYPE > &row) const
returns a copy of a row of the matrix
Definition: Matrix.h:108
TYPE * getData()
returns a pointer to our data array
Definition: Vector.h:106
A class to represent vectors of numbers.
Definition: Vector.h:28
unsigned int d_dataSize
Definition: Matrix.h:237
TYPE * getData()
returns a pointer to our data array
Definition: Matrix.h:132
unsigned int getDataSize() const
Definition: Matrix.h:86
Matrix(const Matrix< TYPE > &other)
copy constructor
Definition: Matrix.h:64