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