diff --git a/Lab3/Lab3 b/Lab3/Lab3 new file mode 100755 index 0000000..ad3c598 Binary files /dev/null and b/Lab3/Lab3 differ diff --git a/Lab3/main.cpp b/Lab3/main.cpp index 5d4fe35..04f24e4 100644 --- a/Lab3/main.cpp +++ b/Lab3/main.cpp @@ -1,7 +1,8 @@ /** * @file main.cpp * @author Trevor Barnes (barnestr@msoe.edu) - * @brief + * @brief The main driver for the matrix implementation. This driver provides + * test for matrix.cpp. Memory leak test were performed using valgrind * @version 1.0 * @date 2022-03-29 * @@ -19,22 +20,58 @@ int main() cin >> rows; cout << "Enter the number of columns in the test matrix: " << endl; cin >> cols; + // Constructor Test Matrix m1(rows,cols); - // add more tests + Matrix m2(rows,cols); + // Assign various arbitrary values for(int i = 0; i < rows; i++){ for(int j = 0; j < cols; j++){ - m1[i][j] = 4.268394 + (i+7)*(j+7); + m1[i][j] = 12.181998*(1+(i*j)); + m2[i][j] = 1.0 + i; } - m1[0][0] = 4.20; - m1[0][1] = 6.9; - m1[0][2] = 1.337; - m1[0][3] = 12.18; - } - cout << m1 << endl; - m1*5; - cout << m1 << endl; - m1.clear(); - cout << m1; + // IO Test + cout << "m1:" << endl << m1; + // Copy Constructor Test with const + const Matrix m1copy(m1); + cout << "m1copy:" << endl << m1copy; + cout << "m2:" << endl << m2; + // Assignment Operator Test + m1 = m2; + cout << "m1 = m2:" << endl << m1; + // Transpose Test + m1 = ~m1; + cout << "~m1:" << endl << m1; + // Named Contructor Test + Matrix ident = Matrix::identity(4); + cout << "Identity matrix of size: " << rows << endl << ident; + Matrix m3(3,4); + Matrix m4(4,3); + for(int i = 0; i < 3; i++){ + for(int j = 0; j < 4; j++){ + m3[i][j] = 1 + i*j; + } + } + cout << "m3:" << endl << m3; + // Scalar Multiplication Test + m3 = 2.0*m3; + cout << "m3 = 2.0*m3" << endl << m3; + for(int i = 0; i < 4; i++){ + for(int j = 0; j < 3; j++){ + m4[i][j] = 2 + i*j; + } + } + cout << "m4:" << endl << m4; + Matrix m5(3,3); + // Matrix Multiplication Test + m5 = m3*m4; + cout << "m5 = m3*m4" << endl << m5; + // Clear Test + m5.clear(); + cout << "m5.clear()" << endl << m5; + + // Tested for memory leaks using valgrind: + // Result: "All heap blocks were freed -- no leaks are possible" + return 0; } diff --git a/Lab3/matrix.cpp b/Lab3/matrix.cpp index 637e35f..3a67460 100644 --- a/Lab3/matrix.cpp +++ b/Lab3/matrix.cpp @@ -1,7 +1,7 @@ /** * @file matrix.cpp * @author Trevor Barnes (barnestr@msoe.edu) - * @brief + * @brief Contains the main functionality for matrices of double values * @version 1.0 * @date 2022-03-29 * @@ -25,39 +25,55 @@ Matrix::Matrix(unsigned int rows, unsigned int cols){ this->cols = cols; // Create the row pointer this->the_matrix = new Row*[rows]; - for(int i = 0; i < rows+1; i++){ + for(int i = 0; i < rows; i++){ // Assign the rows of the matrix to new memory this->the_matrix[i] = new Row(cols); } } - + // Copy constructor Matrix::Matrix(const Matrix& from){ // New matrix gets row amount from "from" matrix this->rows = from.rows; - // New matrix gets row amount from "from" matrix + // New matrix gets col amount from "from" matrix this->cols = from.cols; // Create the row pointer with new row amount this->the_matrix = new Row*[rows]; - for(int i = 0; i < rows+1; i++){ + for(int i = 0; i < rows; i++){ // Set the pointer to each copied row - the_matrix[i] = new Row(from[i]); + this->the_matrix[i] = new Row(from[i]); } } // Destructor Matrix::~Matrix(){ - // Explicitly calls the destructor for each row in the matrix - for(int i = 0; i < rows+1; i++) { - the_matrix[i]->~Row(); + // Iterates through the pointer array and deletes each row's array + for(int i = 0; i < rows; i++) { + delete this->the_matrix[i]; } // Deletes the matrix itself delete[] the_matrix; } -// Assignment operator - TODO +// Assignment operator Matrix& Matrix::operator=(const Matrix& rhs){ - // finish + if(&rhs != this){ + if(rows > 0 && cols > 0){ + // Iterates through the pointer array and deletes each row's array + for(int i = 0; i < rows; i++) { + delete this->the_matrix[i]; + } + // Deletes the matrix itself + delete[] the_matrix; + } + this->rows = rhs.rows; + this->cols = rhs.cols; + this->the_matrix = new Row*[rows]; + for(int i = 0; i < rows; i++){ + // Set the pointer to each copied row + the_matrix[i] = new Row(rhs[i]); + } + } return *this; } @@ -67,7 +83,6 @@ Matrix Matrix::identity(unsigned int size){ if(size < 1){ throw(out_of_range("rows and cols must be greater than 0")); } - size--; // Create square matrix Matrix result(size, size); for(int i = 0; i < size; i++){ @@ -77,46 +92,62 @@ Matrix Matrix::identity(unsigned int size){ return result; } -// Matrix addition - TODO +// Matrix addition Matrix Matrix::operator+(const Matrix& rhs) const{ + if(rows != rhs.rows || cols != rhs.cols){ + throw(out_of_range("Matrices must be the same size")); + } Matrix result(this->rows, this->cols); - // finish + for(int i = 0; i < rows; i++){ + for(int j = 0; j < cols; j++){ + result[i][j] = (*the_matrix[i])[j] + rhs[i][j]; + } + } return result; } -// Matrix multiplication - TODO +// Matrix multiplication Matrix Matrix::operator*(const Matrix& rhs) const{ - if(rows != rhs.cols){ - throw(invalid_argument("1st matrix rows must equal 2nd matrix cols")); + if(cols != rhs.rows){ + throw(out_of_range("1st matrix rows must equal 2nd matrix cols")); } - //for(int i = 0; i < cols; i++) Matrix result(this->rows, rhs.cols); - // finish + for(int i = 0; i < this->rows; i++){ + for(int j = 0; j < rhs.cols; j++){ + result[i][j] = 0.0; + for(int k = 0; k < rhs.rows; k++){ + result[i][j] += (*the_matrix[i])[k]*rhs[k][j]; + } + } + } return result; } // Scalar multiplication Matrix Matrix::operator*(const double scale) const{ + Matrix result(this->rows, this->cols); for(int i = 0; i < rows; i++){ for(int j = 0; j < cols; j++){ - (*the_matrix[i])[j] = (*the_matrix[i])[j]*scale; + result[i][j] = (*the_matrix[i])[j]*scale; } } - Matrix result(this->rows, this->cols); - // finish return result; } -// Transpose of a Matrix - TODO +// Transpose of a Matrix Matrix Matrix::operator~() const{ Matrix result(this->cols, this->rows); - // finish + for(int i = 0; i < rows; i++){ + for(int j = 0; j < cols; j++){ + result[j][i] = (*the_matrix[i])[j]; + } + } return result; } // Clear Matrix void Matrix::clear(){ - for(int i = 0; i < rows+1; i++) { + for(int i = 0; i < rows; i++) { the_matrix[i]->clear(); } } @@ -139,7 +170,7 @@ const Row& Matrix::operator[](unsigned int row) const{ return *(the_matrix[row]); } -// print to output stream - TODO +// print to output stream void Matrix::out(std::ostream& os) const{ os << setprecision(4); os << "["; @@ -160,7 +191,6 @@ void Matrix::out(std::ostream& os) const{ } } os << "]" << endl; - // finish } // global insertion operator @@ -169,7 +199,7 @@ std::ostream& operator<<(std::ostream& os, const Matrix& rhs){ return os; } -// global scalar multiplication - TODO +// global scalar multiplication Matrix operator*(const double scale, const Matrix& rhs){ return rhs*scale; } \ No newline at end of file