This repository has been archived by the owner on Feb 3, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Matrix.h
243 lines (201 loc) · 7.3 KB
/
Matrix.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#ifndef MATRIX_MATRIX_H
#define MATRIX_MATRIX_H
#include <memory>
#include <string>
#include <iostream>
#include "MatrixData.h"
#include "SumMD.h"
#include "MultiplyMD.h"
#include "MatrixIterator.h"
#include "MatrixCell.h"
template<unsigned ROWS, unsigned COLUMNS, typename T, class MD>
class StaticSizeMatrix;
/**
* The only class exposed to the user of the library. It provides every method needed to use the matrix.
* @tparam T the type of the data contained in each matrix cell
*/
template<typename T, class MD = VectorMatrixData<T>>
class Matrix {
private:
//This allows us to access protected members of another Matrix of a different type
template<typename U, class MDD> friend
class Matrix;
//This allows us to access protected members of another StaticSizeMatrix of a different size
template<unsigned R, unsigned C, typename U, class MDD> friend
class StaticSizeMatrix;
protected:
MD data; //Pointer to the class holding the data
/** Private constructor that accepts a pointer to the data */
explicit Matrix(MD data) : data(data) {}
public:
/**
* Base constructor that creates a new matrix of the given size
* @param rows number of rows
* @param columns number of columns
*/
explicit Matrix(unsigned rows, unsigned columns) : data(VectorMatrixData<T>(rows, columns)) {
}
Matrix(const Matrix<T, MD> &other) : data(other.data.copy()) {}
/**
* Move constructor. Default behaviour.
* @param other the other matrix
*/
Matrix(Matrix<T, MD> &&other) noexcept = default;
MD &getData() {
return this->data;
}
const T operator()(unsigned row, unsigned col) const {
if (row < 0 || row >= this->rows()) {
Utils::error("Row out of bounds");
} else if (col < 0 || col >= this->columns()) {
Utils::error("Column out of bounds");
}
return this->data.get(row, col);
}
MatrixCell<T, MD> operator()(unsigned row, unsigned col) {
return MatrixCell<T, MD>(this->data, row, col);
}
/**
* @return the number of columns
*/
unsigned columns() const {
return this->data.columns();
}
/**
* @return the number of rows
*/
unsigned rows() const {
return this->data.rows();
}
/**
* @return the total number of cells (rows*columns)
*/
unsigned size() const {
return rows() * columns();
}
Matrix<T, SubmatrixMD<T, MD>> submatrix(unsigned rowOffset, unsigned colOffset, unsigned rows, unsigned columns) {
return Matrix<T, SubmatrixMD<T, MD>>(SubmatrixMD<T, MD>(rowOffset, colOffset, rows, columns, this->data));
}
const Matrix<T, SubmatrixMD<T, MD>> submatrix(unsigned rowOffset, unsigned colOffset, unsigned rows, unsigned columns) const {
return Matrix<T, SubmatrixMD<T, MD>>(SubmatrixMD<T, MD>(rowOffset, colOffset, rows, columns, this->data));
}
template<unsigned ROW_COUNT, unsigned COL_COUNT>
StaticSizeMatrix<ROW_COUNT, COL_COUNT, T, SubmatrixMD<T, MD>> submatrix(unsigned rowOffset, unsigned colOffset) {
return StaticSizeMatrix<ROW_COUNT, COL_COUNT, T, SubmatrixMD<T, MD>>(
SubmatrixMD<T, MD>(rowOffset, colOffset, ROW_COUNT, COL_COUNT, this->data));
}
template<unsigned ROW_COUNT, unsigned COL_COUNT>
const StaticSizeMatrix<ROW_COUNT, COL_COUNT, T, SubmatrixMD<T, MD>> submatrix(unsigned rowOffset, unsigned colOffset) const {
return StaticSizeMatrix<ROW_COUNT, COL_COUNT, T, SubmatrixMD<T, MD>>(
SubmatrixMD<T, MD>(rowOffset, colOffset, ROW_COUNT, COL_COUNT, this->data));
}
Matrix<T, TransposedMD<T, MD>> transpose() {
return Matrix<T, TransposedMD<T, MD>>(TransposedMD<T, MD>(this->data));
}
const Matrix<T, TransposedMD<T, MD>> transpose() const {
return Matrix<T, TransposedMD<T, MD>>(TransposedMD<T, MD>(this->data));
}
Matrix<T, DiagonalMD<T, MD>> diagonal() {
return Matrix<T, DiagonalMD<T, MD>>(DiagonalMD<T, MD>(this->data));
}
const Matrix<T, DiagonalMD<T, MD>> diagonal() const {
return Matrix<T, DiagonalMD<T, MD>>(DiagonalMD<T, MD>(this->data));
}
/**
* Can only be called on a vector.
* @return an immutable diagonal square matrix that has this vector as diagonal and <code>0</code> (zero) in all other positions.
*/
const Matrix<T, DiagonalMatrixMD<T, MD>> diagonalMatrix() const {
return Matrix<T, DiagonalMatrixMD<T, MD>>(DiagonalMatrixMD<T, MD>(this->data));
}
/**
* Multiplies the two given matrices
*/
template<class MD2>
const Matrix<T, MultiplyMD<T, MD, MD2>> operator*(const Matrix<T, MD2> &another) const {
return Matrix<T, MultiplyMD<T, MD, MD2>>(
MultiplyMD<T, MD, MD2>(this->data, another.data));
}
/**
* Adds the two given matrices
*/
template<class MD2>
const Matrix<T, SumMDa<T, MD, MD2>> operator+(const Matrix<T, MD2> &another) const {
return Matrix<T, SumMDa<T, MD, MD2>>(
SumMDa<T, MD, MD2>(this->data, another.data));
}
template<unsigned ROWS, unsigned COLUMNS, class MD2>
const StaticSizeMatrix<ROWS, COLUMNS, T, SumMDa<T, MD2, MD>>
operator+(const StaticSizeMatrix<ROWS, COLUMNS, T, MD2> &another) const {
return another + (*this);
}
/**
* @return true if this matrix is a square (has the same number of rows and columns)
*/
bool isSquared() const {
return rows() == columns();
}
/**
* @return true if this matrix is a vector (has only one column)
*/
bool isVector() const {
return columns() == 1;
}
/**
* @return true if this matrix is a covector (has only one row)
*/
bool isCovector() const {
return rows() == 1;
}
/**
* @return an iterator on the first position. This iterator moves from left to right, and then top to bottom.
*/
MatrixRowMajorIterator<T, MD> beginRowMajor() const {
return MatrixRowMajorIterator<T, MD>(this->data, 0, 0);
}
/**
* @return an iterator on the last position. This iterator moves from left to right, and then top to bottom.
*/
MatrixRowMajorIterator<T, MD> endRowMajor() const {
return MatrixRowMajorIterator<T, MD>(this->data, rows(), 0);
}
/**
* @return an iterator on the first position. This iterator moves from top to bottom, and then left to right.
*/
MatrixColumnMajorIterator<T, MD> beginColumnMajor() const {
return MatrixColumnMajorIterator<T, MD>(this->data, 0, 0);
}
/**
* @return an iterator on the last position. This iterator moves from top to bottom, and then left to right.
*/
MatrixColumnMajorIterator<T, MD> endColumnMajor() const {
return MatrixColumnMajorIterator<T, MD>(this->data, 0, columns());
}
Matrix<T, VectorMatrixData<T>> copy() const {
return Matrix<T, VectorMatrixData<T>>(VectorMatrixData<T>::template toVector<MD>(this->data));
}
template<typename U>
Matrix<U, MatrixCaster<U, MD>> cast() const {
return Matrix<U, MatrixCaster<U, MD>>(MatrixCaster<U, MD>(this->data));
}
/**
* Prints the content of this matrix to the standard output
* @param format the format string to use when printing values
* @param separator the separator between each column
*/
void print(const char *format, const char *separator = " ") const {
for (unsigned row = 0; row < this->rows(); ++row) {
for (unsigned col = 0; col < this->columns(); ++col) {
if (col > 0) {
std::cout << separator;
}
//Since we are mixing cout and format, buffers need to be flushed
std::cout.flush();
printf(format, (T) (*this)(row, col));
fflush(stdout);
}
std::cout << std::endl;
}
}
};
#endif //MATRIX_MATRIX_H