-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMatrix.cpp
368 lines (292 loc) · 8.97 KB
/
Matrix.cpp
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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
/**
This is the implementation of the
functions defined in the header
file.
**/
#include "Matrix.h"
// default constructor, set rows/cols to 0
Matrix::Matrix()
{
setRowCount(0);
setColCount(0);
theMatrix = 0;
}
// create matrix with given rows/col
Matrix::Matrix(int rows, int cols)
{
if((rows < 0) | (cols < 0)) {
cout << "Dimensions must be greater or equal to 0." << endl;
}
// set rows and columns
setRowCount(rows);
setColCount(cols);
// allocate memory to rows of the matrix
// by creating an array of float pointers
// with size of rows
theMatrix = new float* [getRowCount()];
// allocate memory to cols of the matrix
// by setting each row pointer to another
// array of floats with size of cols
for(int i=0; i<getRowCount(); i++) {
theMatrix[i] = new float [getColCount()];
}
// zero each element of the matrix
for(int i=0; i<getRowCount(); i++) {
for(int j=0; j<getColCount(); j++) {
theMatrix[i][j] = 0;
}
}
}
// copy constructor
Matrix::Matrix(const Matrix& other)
{
// set the dimensions
setRowCount(other.getRowCount());
setColCount(other.getColCount());
// allocate the memory
theMatrix = new float* [other.getRowCount()];
for(int i=0; i<other.getRowCount(); i++) {
theMatrix[i] = new float [other.getColCount()];
}
// assign each value
for(int i=0; i<other.getRowCount(); i++) {
for(int j=0; j<other.getColCount(); j++) {
this->access(i, j) = other.access(i, j);
}
}
}
// move constructor, efficient in expressions
// like a = x + y;
Matrix::Matrix(Matrix&& that)
{
// set "this" matrix's data to "that" matrix's data
m_rows = that.m_rows;
m_cols = that.m_cols;
theMatrix = that.theMatrix;
// delete data in "that" matrix
that.setRowCount(0);
that.setColCount(0);
that.theMatrix = 0;
}
// create matrix from a file
// NOTE: the file must not have blank lines at the end
Matrix::Matrix(char* fileName)
{
// declare and open the file
ifstream theFile;
theFile.open(fileName);
// if the file is there..
if(theFile != NULL) {
// till the end of the file..
while( !theFile.eof() ) {
// place file info into calling matrix object
// using the >> operator we defined
theFile >> *this;
}
// close file
theFile.close();
}
else {
cout << "Unable to open: " << fileName << endl;
}
}
Matrix::~Matrix()
{
// destroy each col in each row
for(int i=0; i<getRowCount(); ++i) {
delete [] theMatrix[i];
}
// destroy the rows
delete [] theMatrix;
}
// used in operator= overloading,
// simply swap all data members from
// the first to the second matrix instead
// of copying
void swap(Matrix& first, Matrix& second)
{
swap(first.m_rows, second.m_rows);
swap(first.m_cols, second.m_cols);
swap(first.theMatrix, second.theMatrix);
}
// returns a reference to a
// position row,col in the matrix
float& Matrix::access(int row, int col) const
{
// check dimensions
if((row > this->getRowCount()) | (col > this->getColCount()) |
(row < 0) | (col < 0)) {
cout << "Dimensions are out of range." << endl;
}
else { // dimensions are good, so return position
return theMatrix[row][col];
}
}
// overloads << and writes matrix to console
ostream& operator<<(ostream& output, Matrix& m)
{
// print row/col
output << m.getRowCount() << " " << m.getColCount() << " " << endl;
// iterate through and print each i,j of the matrix
for(int i=0; i<m.getRowCount(); i++){
for(int j=0; j<m.getColCount(); j++) {
output << m.access(i, j) << " ";
// newline for each row
if( j == m.getColCount() - 1) {
output << endl;
}
}
}
output << endl;
return output;
}
istream &operator>>(istream& input, Matrix& m)
{
// get the rows and columns
input >> skipws >> m.m_rows >> m.m_cols;
// allocate memory
m.theMatrix = new float* [m.getRowCount()];
for(int i=0; i<m.getRowCount(); i++) {
m.theMatrix[i] = new float [m.getColCount()];
}
// get each element
for(int i=0; i<m.getRowCount(); i++) {
for(int j=0; j<m.getColCount(); j++) {
input >> skipws >> m.access(i,j);
}
}
return input;
}
// returns the transpose of the matrix
Matrix operator!(const Matrix &m)
{
// create the result, it has reverse dimensions
Matrix result(m.getColCount(), m.getRowCount());
// iterate through
for(int i=0; i<m.getRowCount(); i++) {
for(int j=0; j<m.getColCount(); j++) {
// reverse the entries
result.access(j,i) = m.access(i, j);
}
}
return result;
}
// assignment operator is overloaded so
// the lhs (this) is idential to the rhs
// note that the parameter is passed-by-value
// for optimization, lets the compiler do the work
Matrix& Matrix::operator=(Matrix m)
{
// check for self assignment
if(this != &m)
{
// use swap for efficieny
swap(*this, m);
return *this;
}
}
// returns a matrix that is equal to lhs+rhs
Matrix operator+(const Matrix &lhs, const Matrix &rhs)
{
// the result to return
Matrix result(rhs.getRowCount(), rhs.getColCount());
// check dimensions
if((lhs.getRowCount() != rhs.getRowCount()) |
(lhs.getColCount() != rhs.getColCount())) {
cout << "Dimensions are not equal, cannot add matrices." << endl;
}
// dimensions are good, so add each element together
else {
// iterate through rhs and lhs
for(int i=0; i<rhs.getRowCount(); i++) {
for(int j=0; j<rhs.getColCount(); j++) {
// put rhs+lhs in result
result.access(i,j) = rhs.access(i, j) + lhs.access(i, j);
}
}
}
return result;
}
// scalar multiplication
Matrix operator*(const float &lhs, const Matrix &rhs)
{
// create the result matrix
Matrix result(rhs.getRowCount(), rhs.getColCount());
// iterate through
for(int i=0; i<rhs.getRowCount(); i++) {
for(int j=0; j<rhs.getColCount(); j++) {
// put lhs * rhs (where lhs is a scalar)
// in result
result.access(i,j) = rhs.access(i, j) * lhs;
}
}
return result;
}
// scalar the other way around
Matrix operator*(const Matrix &rhs, const float &lhs)
{
// create the result matrix
Matrix result(rhs.getRowCount(), rhs.getColCount());
// iterate through
for(int i=0; i<rhs.getRowCount(); i++) {
for(int j=0; j<rhs.getColCount(); j++) {
// put lhs * rhs (where lhs is a scalar)
// in result
result.access(i,j) = rhs.access(i, j) * lhs;
}
}
return result;
}
// multiplication is currently O(n^3) but
// working on implementing Strassen's algo
// to optimize..
Matrix operator*(const Matrix &lhs, const Matrix &rhs)
{
// create the result matrix
// it has rows of lhs and cols of rhs
Matrix result(lhs.getRowCount(), rhs.getColCount());
// check dimensions
if( (lhs.getRowCount() != rhs.getColCount()) |
(lhs.getColCount() != rhs.getRowCount()) ) {
cout << "Dimensions are not condusive for matrix multiplication." << endl;
}
else {
// iterate through
for(int i=0; i<lhs.getRowCount(); i++) {
for(int j=0; j<rhs.getColCount(); j++) {
float sum =0;
for(int k=0; k < rhs.getRowCount(); k++ ) {
sum += lhs.access(i, k) * rhs.access(k, j);
}
result.access(i,j) = sum;
}
}
}
return result;
}
// equality operator returns true if matricies are identical
bool operator==(const Matrix &lhs, const Matrix &rhs)
{
// check dimensions
if( (lhs.getRowCount() != rhs.getRowCount()) |
(lhs.getColCount() != rhs.getColCount()) ) {
// dimensions are not equal
return false;
}
else {
// check each element
for(int i=0; i<lhs.getRowCount(); i++) {
for(int j=0; j<lhs.getColCount(); j++) {
if(lhs.access(i,j) != rhs.access(i,j)) {
return false;
}
}
}
}
return true;
}
bool operator!=(const Matrix &lhs, const Matrix &rhs)
{
// simply the opposite of the == operand
return !(lhs == rhs);
}