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