RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
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
25namespace RDNumeric {
26
27//! A matrix class for general, non-square matrices
28template <class TYPE>
29class 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_data() {}
233 unsigned int d_nRows{0};
234 unsigned int d_nCols{0};
235 unsigned int d_dataSize{0};
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 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*/
254template <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*/
301template <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}; // namespace RDNumeric
328
329//! ostream operator for Matrix's
330template <class TYPE>
331std::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::setfill(' ') << std::setw(7) << std::setprecision(3)
341 << mat.getVal(i, j) << " ";
342 }
343 target << "\n";
344 }
345 return target;
346}
347
348#endif
#define CHECK_INVARIANT(expr, mess)
Definition Invariant.h:101
#define PRECONDITION(expr, mess)
Definition Invariant.h:109
std::ostream & operator<<(std::ostream &target, const RDNumeric::Matrix< TYPE > &mat)
ostream operator for Matrix's
Definition Matrix.h:331
A matrix class for general, non-square matrices.
Definition Matrix.h:29
Matrix(unsigned int nRows, unsigned int nCols)
Initialize with a size.
Definition Matrix.h:34
unsigned int d_dataSize
Definition Matrix.h:235
virtual TYPE getVal(unsigned int i, unsigned int j) const
returns a particular element of the matrix
Definition Matrix.h:87
virtual Matrix< TYPE > & transpose(Matrix< TYPE > &transpose) const
copies the transpose of this Matrix into another, returns the result
Definition Matrix.h:211
virtual Matrix< TYPE > & operator+=(const Matrix< TYPE > &other)
Matrix addition.
Definition Matrix.h:152
Matrix(unsigned int nRows, unsigned int nCols, DATA_SPTR data)
Initialize from a pointer.
Definition Matrix.h:57
unsigned int d_nRows
Definition Matrix.h:233
virtual Matrix< TYPE > & operator/=(TYPE scale)
division by a scalar
Definition Matrix.h:194
virtual ~Matrix()
Definition Matrix.h:76
virtual void getRow(unsigned int i, Vector< TYPE > &row) const
returns a copy of a row of the matrix
Definition Matrix.h:104
unsigned int getDataSize() const
Definition Matrix.h:84
TYPE * getData()
returns a pointer to our data array
Definition Matrix.h:128
unsigned int numRows() const
returns the number of rows
Definition Matrix.h:79
virtual Matrix< TYPE > & operator*=(TYPE scale)
Multiplication by a scalar.
Definition Matrix.h:184
unsigned int numCols() const
returns the number of columns
Definition Matrix.h:82
Matrix(const Matrix< TYPE > &other)
copy constructor
Definition Matrix.h:65
DATA_SPTR d_data
Definition Matrix.h:236
unsigned int d_nCols
Definition Matrix.h:234
boost::shared_array< TYPE > DATA_SPTR
Definition Matrix.h:31
virtual Matrix< TYPE > & operator-=(const Matrix< TYPE > &other)
Matrix subtraction.
Definition Matrix.h:169
const TYPE * getData() const
returns a const pointer to our data array
Definition Matrix.h:131
Matrix(unsigned int nRows, unsigned int nCols, TYPE val)
Initialize with a size and default value.
Definition Matrix.h:42
virtual void setVal(unsigned int i, unsigned int j, TYPE val)
sets a particular element of the matrix
Definition Matrix.h:95
virtual void getCol(unsigned int i, Vector< TYPE > &col) const
returns a copy of a column of the matrix
Definition Matrix.h:115
Matrix< TYPE > & assign(const Matrix< TYPE > &other)
Copy operator.
Definition Matrix.h:137
A class to represent vectors of numbers.
Definition Vector.h:29
unsigned int size() const
return the size (dimension) of the vector
Definition Vector.h:78
TYPE * getData()
returns a pointer to our data array
Definition Vector.h:103
Matrix< TYPE > & multiply(const Matrix< TYPE > &A, const Matrix< TYPE > &B, Matrix< TYPE > &C)
Matrix multiplication.
Definition Matrix.h:255
Matrix< double > DoubleMatrix
Definition Matrix.h:326