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