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