Peano
Loading...
Searching...
No Matches
DynamicMatrix.cpp
Go to the documentation of this file.
1#include "DynamicMatrix.h"
2
3#include <cstring>
4#include <iostream>
5
8
9#ifdef UseOpenblas
10#include <cblas.h>
11#endif
12
19
21 const tarch::la::DynamicMatrix& lhs,
22 const tarch::la::DynamicMatrix& rhs,
23 bool innerProduct
24) {
25 if (innerProduct) {
26 assertionMsg(false, "not implemented yet");
27 } else {
28 _rows = lhs._rows * rhs._rows;
29 _cols = lhs._cols * rhs._cols;
30
31 _m = tarch::allocateMemory<double>(
32 _rows * _cols,
34 );
35
36 for (int lhsRow = 0; lhsRow < lhs._rows; lhsRow++)
37 for (int rhsRow = 0; rhsRow < rhs._rows; rhsRow++)
38 for (int lhsCol = 0; lhsCol < lhs._cols; lhsCol++)
39 for (int rhsCol = 0; rhsCol < rhs._cols; rhsCol++) {
41 lhsRow * rhs._rows + rhsRow,
42 lhsCol * rhs._cols + rhsCol
43 )] = lhs._m[lhs.serialise(lhsRow, lhsCol)]
44 * rhs._m[rhs.serialise(rhsRow, rhsCol)];
45 }
46 }
47}
48
50 int rows,
51 int cols,
52 std::initializer_list<std::initializer_list<double>> values
53):
54 _cols(cols),
55 _rows(rows),
56 _m(nullptr) {
57 _m = tarch::allocateMemory<double>(rows * cols, tarch::MemoryLocation::Heap);
58
59 int index = 0;
60 for (typename std::initializer_list<
61 std::initializer_list<double>>::const_iterator p
62 = values.begin();
63 p != values.end();
64 p++)
65 for (typename std::initializer_list<double>::const_iterator pp = p->begin();
66 pp != p->end();
67 pp++) {
68 _m[index] = *pp;
69 index++;
70 }
71}
72
74 _cols(rhs._cols),
75 _rows(rhs._rows),
76 _m(nullptr) {
77 _m = tarch::allocateMemory<double>(
78 _rows * _cols,
80 );
81 memcpy(_m, rhs._m, _cols * _rows * sizeof(double));
82}
83
85 _cols(rhs._cols),
86 _rows(rhs._rows),
87 _m(rhs._m) {
88 rhs._m = nullptr;
89 rhs._cols = 0;
90 rhs._rows = 0;
91}
92
93tarch::la::DynamicMatrix::DynamicMatrix(int rows, int cols, double* data):
94 _cols(cols),
95 _rows(rows),
96 _m(data) {}
97
99 std::initializer_list<std::initializer_list<double>> values
100) {
101 int index = 0;
102 for (typename std::initializer_list<
103 std::initializer_list<double>>::const_iterator p
104 = values.begin();
105 p != values.end();
106 p++)
107 for (typename std::initializer_list<double>::const_iterator pp = p->begin();
108 pp != p->end();
109 pp++) {
110 assertion3(index < _cols * _rows, _cols, _rows, index);
111 _m[index] = *pp;
112 index++;
113 }
114 return *this;
115}
116
118 _cols(cols),
119 _rows(rows),
120 _m(nullptr) {
121 _m = tarch::allocateMemory<double>(rows * cols, tarch::MemoryLocation::Heap);
122 std::fill_n(_m, rows * cols, 0.0);
123}
124
125/*
126tarch::la::DynamicMatrix::DynamicMatrix(const DynamicMatrix&& value):
127 _cols(value._cols),
128 _rows(value._rows),
129 _m(value._m) {
130}
131*/
132
138
140 bool result = (_rows == matrix._rows and _cols == matrix._cols);
141
142 for (int col = 0; col < _cols; col++)
143 for (int row = 0; row < _rows; row++) {
144 result &= tarch::la::equals(
145 _m[serialise(row, col)],
146 matrix._m[serialise(row, col)]
147 );
148 }
149
150 return result;
151}
152
154 assertion4(row >= 0, row, col, _rows, _cols);
155 assertion4(col >= 0, row, col, _rows, _cols);
156 assertion4(row < _rows, row, col, _rows, _cols);
157 assertion4(col < _cols, row, col, _rows, _cols);
158 return _m[serialise(row, col)];
159}
160
162 assertion(row >= 0);
163 assertion(col >= 0);
164 assertion(row < _rows);
165 assertion(col < _cols);
166 return _m[serialise(row, col)];
167}
168
170 tarch::la::DynamicMatrix result(rows, rows);
171 for (int i = 0; i < rows; i++) {
172 result(i, i) = 1.0;
173 }
174 return result;
175}
176
178 for (int col = 0; col < _cols; col++)
179 for (int row = 0; row < _rows; row++) {
180 _m[serialise(row, col)] *= value;
181 }
182}
183
184void tarch::la::DynamicMatrix::multiply(double* result, double* x) {
185 std::fill_n(result, _rows, 0.0);
186
187 /* for (int col=0; col<_cols; col++)
188 for (int row=0; row<_rows; row++) {
189 result[row] += _m[ serialise(row,col) ] * x[row];
190 }
191 */
192
193 for (int row = 0; row < _rows; row++) {
194 for (int col = 0; col < _cols; col++) {
195 result[row] += _m[serialise(row, col)] * x[col];
196 }
197 }
198}
199
201 double* result,
202 const DynamicMatrix& matrix
203) const {
204 std::fill_n(result, _rows * matrix.cols(), 0.0);
205
206 for (int row = 0; row < _rows; row++) {
207 for (int col = 0; col < matrix.cols(); col++) {
208 for (int i = 0; i < _cols; i++) {
209 result[row * matrix.cols() + col] += (*this)(row, i) * matrix(i, col);
210 }
211 }
212 }
213}
214
215std::string tarch::la::DynamicMatrix::toString(bool addLineBreaks) const {
216 std::ostringstream msg;
217 msg << "(rows=" << _rows << ",cols=" << _cols << ",{";
218 if (addLineBreaks)
219 msg << std::endl;
220 for (int row = 0; row < _rows; row++) {
221 if (addLineBreaks)
222 msg << std::endl;
223 else {
224 if (row != 0)
225 msg << ",";
226 msg << "{";
227 }
228
229 for (int col = 0; col < _cols; col++) {
230 if (addLineBreaks)
231 msg << " ";
232 else if (col != 0)
233 msg << ",";
234 msg << _m[serialise(row, col)];
235 }
236
237 if (not addLineBreaks)
238 msg << "}";
239 }
240 if (addLineBreaks)
241 msg << std::endl;
242 msg << "})";
243 return msg.str();
244}
245
247 vectorToString(double* values, int entries, bool addLineBreaks) {
248 std::ostringstream msg;
249 msg << "(entries=" << entries << ",{";
250 for (int i = 0; i < entries; i++) {
251 if (addLineBreaks)
252 msg << std::endl;
253 else {
254 if (i != 0)
255 msg << ",";
256 msg << values[i];
257 }
258 }
259 msg << "})";
260 return msg.str();
261}
262
264 double* __restrict__ result,
265 const double* __restrict__ x,
266 int batchCount
267) {
268 batchedMultiplyAoS(result, x, batchCount, _rows, 0);
269}
270
272 double* __restrict__ result,
273 const double* __restrict__ x,
274 int batchSize,
275 int resultSize,
276 int firstRow
277) {
278 assertion3(batchSize > 0, batchSize, resultSize, firstRow);
279 assertion3(resultSize > 0, batchSize, resultSize, firstRow);
280 assertion3(firstRow >= 0, batchSize, resultSize, firstRow);
281
282 std::fill_n(result, resultSize * batchSize, 0.0);
283
284 for (int col = 0; col < _cols; col++) {
285 for (int rowInResult = 0; rowInResult < resultSize; rowInResult++)
286#ifdef SharedOMP
287#pragma omp simd
288#endif
289 for (int i = 0; i < batchSize; i++) {
291 rowInResult + firstRow < _rows,
292 batchSize,
293 resultSize,
294 firstRow
295 );
296 result[rowInResult * batchSize + i]
297 += _m[serialise(rowInResult + firstRow, col)]
298 * x[col * batchSize + i];
299 }
300 }
301}
302
304 insertEmptyColumns(int number, int where, int repeatEveryKColumns) {
305 assertion4(number > 0, number, where, repeatEveryKColumns, toString());
306 assertion4(where >= 0, number, where, repeatEveryKColumns, toString());
307 assertion4(where <= _cols, number, where, repeatEveryKColumns, toString());
309 repeatEveryKColumns >= 0,
310 number,
311 where,
312 repeatEveryKColumns,
313 toString()
314 );
315
316 double* oldData = _m;
317 int oldRows = _rows;
318 int oldCols = _cols;
319
320 const int numberOfInsertions = repeatEveryKColumns == 0
321 ? number
322 : (_cols / repeatEveryKColumns) * number;
323 _cols += numberOfInsertions;
324
325 _m = tarch::allocateMemory<double>(
326 _rows * _cols,
328 );
329 std::fill_n(_m, _rows * _cols, 0.0);
330
331 int imageColumn = 0;
332 for (int col = 0; col < oldCols; col++) {
333 if (col == where) {
334 imageColumn += number;
335 if (repeatEveryKColumns >= 1) {
336 where += repeatEveryKColumns;
337 }
338 }
339 for (int row = 0; row < oldRows; row++) {
340 _m[serialise(row, imageColumn)] = oldData
341 [serialise(row, col, oldRows, oldCols)];
342 }
343 imageColumn++;
344 }
345
347}
348
350 insertEmptyRows(int number, int where, int repeatEveryKRows) {
351 assertion4(number > 0, number, where, repeatEveryKRows, toString());
352 assertion4(where >= 0, number, where, repeatEveryKRows, toString());
353 assertion4(where < _cols, number, where, repeatEveryKRows, toString());
354 assertion4(repeatEveryKRows >= 0, number, where, repeatEveryKRows, toString());
355
356 double* oldData = _m;
357 int oldRows = _rows;
358 int oldCols = _cols;
359
360 const int numberOfInsertions = repeatEveryKRows == 0
361 ? number
362 : (_rows / repeatEveryKRows) * number;
363 _rows += numberOfInsertions;
364
365 _m = tarch::allocateMemory<double>(
366 _rows * _cols,
368 );
369 std::fill_n(_m, _rows * _cols, 0.0);
370
371 int imageRow = 0;
372 for (int row = 0; row < oldRows; row++) {
373 if (row == where) {
374 imageRow += number;
375 if (repeatEveryKRows >= 1) {
376 where += repeatEveryKRows;
377 }
378 }
379 for (int col = 0; col < oldCols; col++) {
380 _m[serialise(imageRow, col)] = oldData
381 [serialise(row, col, oldRows, oldCols)];
382 }
383 imageRow++;
384 }
385
387}
388
390 double* oldData = _m;
391 int oldRows = _rows;
392 int oldCols = _cols;
393 _cols--;
394
395
396 _m = tarch::allocateMemory<double>(
397 _rows * _cols,
399 );
400 std::fill_n(_m, _rows * _cols, 0.0);
401
402 for (int col = 0; col < _cols; col++)
403 for (int row = 0; row < _rows; row++) {
404 int preImageColumn = col < number ? col : col + 1;
405 _m[serialise(row, col)] = oldData
406 [serialise(row, preImageColumn, oldRows, oldCols)];
407 }
408
410}
411
412void tarch::la::DynamicMatrix::shiftRowsDown(int shift, bool wrap) {
413 double* oldData = _m;
414 _m = tarch::allocateMemory<double>(
415 _rows * _cols,
417 );
418 std::fill_n(_m, _rows * _cols, 0.0);
419
420 for (int col = 0; col < _cols; col++)
421 for (int row = 0; row < _rows; row++) {
422 int imageRow = row + shift;
423 if (wrap)
424 imageRow %= _rows;
425 if (imageRow >= 0 and imageRow < _rows) {
426 _m[serialise(imageRow, col)] = oldData[serialise(row, col)];
427 }
428 }
429
431}
432
434 double* oldData = _m;
435 _m = tarch::allocateMemory<double>(
436 _rows * _cols,
438 );
439 std::fill_n(_m, _rows * _cols, 0.0);
440
441 for (int col = 0; col < _cols; col++)
442 for (int row = 0; row < _rows; row++) {
443 int imageCol = col + shift;
444 if (wrap)
445 imageCol %= _cols;
446 if (imageCol >= 0 and imageCol < _cols) {
447 _m[serialise(row, imageCol)] = oldData[serialise(row, col)];
448 }
449 }
450
452}
453
454int tarch::la::DynamicMatrix::rows() const { return _rows; }
455
456int tarch::la::DynamicMatrix::cols() const { return _cols; }
457
459 int blockSize,
460 int numberOfReplications,
461 int shiftAfterEveryReplication,
462 bool extendColumnsToAccommodateShifts
463) {
465 blockSize >= 1,
466 blockSize,
467 numberOfReplications,
468 shiftAfterEveryReplication
469 );
471 _rows % blockSize == 0,
472 blockSize,
473 numberOfReplications,
474 shiftAfterEveryReplication
475 );
477 numberOfReplications >= 2,
478 blockSize,
479 numberOfReplications,
480 shiftAfterEveryReplication
481 );
482
483 double* oldData = _m;
484 int oldRows = _rows;
485 int oldCols = _cols;
486
488 numberOfReplications >= 1,
489 numberOfReplications,
490 shiftAfterEveryReplication
491 );
493 shiftAfterEveryReplication >= 0,
494 numberOfReplications,
495 shiftAfterEveryReplication
496 );
497
498 const int numberOfBlocks = _rows / blockSize;
499 _rows = _rows * numberOfReplications;
500 if (extendColumnsToAccommodateShifts) {
501 _cols = _cols + shiftAfterEveryReplication * (numberOfReplications - 1);
502 }
503
504 _m = tarch::allocateMemory<double>(
505 _rows * _cols,
507 );
508
509 std::fill_n(_m, _rows * _cols, 0.0);
510
511 for (int block = 0; block < numberOfBlocks; block++) {
512 for (int replication = 0; replication < numberOfReplications;
513 replication++) {
514 for (int blockRow = 0; blockRow < blockSize; blockRow++) {
515 const int destRow = (block * numberOfReplications + replication
516 ) * blockSize
517 + blockRow;
518 const int srcRow = block * blockSize + blockRow;
519 for (int col = 0; col < oldCols; col++) {
520 const int destCol = col + replication * shiftAfterEveryReplication;
521 if (destCol < _cols) {
522 _m[serialise(destRow, destCol)] = oldData
523 [serialise(srcRow, col, oldRows, oldCols)];
524 }
525 }
526 }
527 }
528 }
529
531}
532
534 int blockSize,
535 int numberOfReplications,
536 int shiftAfterEveryReplication,
537 bool extendColumnsToAccommodateShifts
538) {
540 blockSize >= 1,
541 blockSize,
542 numberOfReplications,
543 shiftAfterEveryReplication
544 );
546 _rows % blockSize == 0,
547 blockSize,
548 numberOfReplications,
549 shiftAfterEveryReplication
550 );
552 numberOfReplications >= 2,
553 blockSize,
554 numberOfReplications,
555 shiftAfterEveryReplication
556 );
557
558 double* oldData = _m;
559 int oldRows = _rows;
560 int oldCols = _cols;
561
563 numberOfReplications >= 1,
564 numberOfReplications,
565 shiftAfterEveryReplication
566 );
568 shiftAfterEveryReplication >= 0,
569 numberOfReplications,
570 shiftAfterEveryReplication
571 );
572
573 const int numberOfBlocks = _cols / blockSize;
574 _cols = _cols * numberOfReplications;
575 if (extendColumnsToAccommodateShifts) {
576 _rows = _rows + shiftAfterEveryReplication * (numberOfReplications - 1);
577 }
578
579 _m = tarch::allocateMemory<double>(
580 _rows * _cols,
582 );
583
584 std::fill_n(_m, _rows * _cols, 0.0);
585
586 for (int block = 0; block < numberOfBlocks; block++) {
587 for (int replication = 0; replication < numberOfReplications;
588 replication++) {
589 for (int blockCol = 0; blockCol < blockSize; blockCol++) {
590 const int destCol = (block * numberOfReplications + replication
591 ) * blockSize
592 + blockCol;
593 const int srcCol = block * blockSize + blockCol;
594 for (int row = 0; row < oldRows; row++) {
595 const int destRow = row + replication * shiftAfterEveryReplication;
596 if (destRow < _rows) {
597 _m[serialise(destRow, destCol)] = oldData
598 [serialise(row, srcCol, oldRows, oldCols)];
599 }
600 }
601 }
602 }
603 }
604
606}
607
611) {
612 tarch::la::DynamicMatrix result(A.rows(), B.cols());
613
614 assertionEquals(A.cols(), B.rows());
615
616#ifdef UseOpenblas
617 cblas_dgemm(
618 CblasRowMajor,
619 CblasNoTrans,
620 CblasNoTrans,
621 A.rows(),
622 B.cols(),
623 A.cols(),
624 1.0,
625 A.data(),
626 A.cols(),
627 B.data(),
628 B.cols(),
629 0.0,
630 result.data(),
631 B.cols()
632 );
633#else
634 for (int row = 0; row < A.rows(); row++)
635 for (int col = 0; col < B.cols(); col++)
636 for (int i = 0; i < A.cols(); i++) {
637 result(row, col) += A(row, i) * B(i, col);
638 }
639#endif
640 return result;
641}
#define assertion2(expr, param0, param1)
#define assertion4(expr, param0, param1, param2, param3)
#define assertion3(expr, param0, param1, param2)
#define assertionEquals(lhs, rhs)
#define assertionMsg(expr, message)
#define assertion(expr)
tarch::la::DynamicMatrix kroneckerProduct(const tarch::la::DynamicMatrix &lhs, const tarch::la::DynamicMatrix &rhs)
Wrapper around static routine, so I don't have to use full-qualified name.
My standard matrix is a matrix where the size is fixed at compile time.
double & operator()(int row, int col)
~DynamicMatrix()
Free the array on the heap.
void multiply(double *result, double *x)
void batchedMultiplyAoS(double *__restrict__ result, const double *__restrict__ x, int batchCount, int resultSize, int firstRow)
This operation assumes that x holds a whole batch of vectors in AoS format.
void insertEmptyRows(int number, int where, int repeatEveryKColumns=0)
static std::string vectorToString(double *values, int entries, bool addLineBreaks=false)
I often need this in combination with the toString() operation above.
void removeColumn(int number)
void multiplyBySmallMatrix(double *result, const DynamicMatrix &matrix) const
void shiftColumnsRight(int shift, bool wrap=false)
DynamicMatrix & operator=(const DynamicMatrix &)=delete
bool operator==(double values[][Cols]) const
void shiftRowsDown(int shift, bool wrap=false)
Shift the rows to the right.
void insertEmptyColumns(int number, int where, int repeatEveryKColumns=0)
Insert zero columns.
void replicateRows(int blockSize, int numberOfReplications, int shiftAfterEveryReplication, bool extendColumnsToAccommodateShifts)
Split the matrix into blocks of rows of size blockSize.
DynamicMatrix(int rows, int cols)
Create empty matrix.
void replicateCols(int blockSize, int numberOfReplications, int shiftAfterEveryReplication, bool extendColumnsToAccommodateShifts)
std::string toString(bool addLineBreaks=false) const
static tarch::la::DynamicMatrix id(int rows)
Create (square) identify matrix with rows rows and column.
static int serialise(int row, int col, int Rows, int Cols)
void scale(double value)
Scale all entries.
Vector< Rows, Scalar > col(const Matrix< Rows, Cols, Scalar > &matrix, int whichColumn)
Extract row from matrix.
Matrix< Rows, Cols, Scalar > operator*(const Matrix< Rows, X, Scalar > &lhs, const Matrix< X, Cols, Scalar > &rhs)
bool equals(const Matrix< Rows, Cols, Scalar > &lhs, const Matrix< Rows, Cols, Scalar > &rhs, const Scalar &tolerance=NUMERICAL_ZERO_DIFFERENCE)
Compares to matrices on equality by means of a numerical accuracy.
Vector< Cols, Scalar > row(const Matrix< Rows, Cols, Scalar > &matrix, int whichRow)
Extract row from matrix.
void freeMemory(void *data, MemoryLocation location, int device=accelerator::Device::HostDevice)
Free memory.
std::string toString(MemoryLocation value)
@ Heap
Create data on the heap of the local device.